scala 高级类型
来源:互联网 发布:跟着兄弟连学php pdf 编辑:程序博客网 时间:2024/06/11 00:27
一 单例类型 this.type
Scala中,对于任何类型的引用v,都可以调用v.type,然后会返回v或者null,有时候这种是有用的,假设一下场景:
比如某一个方法返回this,
classPerson {
private var name:String= null
private var age:Int = 0
def setName(name:String)={
this.name=name
//返回对象本身
this
}
def setAge(age:Int)={
this.age=age
//返回对象本身
this
}
override def toString()="name:"+name+" age:"+age
}
那么我们就可以完成链式调用,如:
object Test extends App { /** * 报错是因为返回的this代表的是父类自己而不是子类自己,而弗雷是没有setStudentNo方法的 * 为解决该问题,可以将setName、setAge方法的返回值设置为:this.type */ println(new Person().setName("john").setAge(22).setStudentNo("2014"))}
然而,如果你还有个子类:
/*当涉及到继承时,会存在一些问题*/class Student extends Person{ private var studentNo:String = null def setStudentNo(no:String) = { this.studentNo=no this } override def toString() = super.toString()+" studetNo:"+studentNo}
然后再来链式调用,就会有问题:
object Test extends App { /** * 报错是因为返回的this代表的是父类自己而不是子类自己,而弗雷是没有setStudentNo方法的 * 为解决该问题,可以将setName、setAge方法的返回值设置为:this.type */ println(new Student().setName("john").setAge(22).setStudentNo("2014"))}
解决办法:
class Person { private var name:String = null private var age:Int = 0 def setName(name:String):this.type = { this.name=name //返回对象本身 this } def setAge(age:Int):this.type={ this.age=age //返回对象本身 this } override def toString()="name:"+name+" age:"+age}
二 类型投影
问题描述,不同对象创建的内部类不是同一种类型:
import scala.collection.mutable.ArrayBufferclass NetWork { class Member(val name:String){ val contacts = new ArrayBuffer[Member]() } private val members = new ArrayBuffer[Member] def join(name:String) = { val m = new Member(name) members += m m }}object Test extends App{ val chatter = new NetWork val myFace = new NetWork /** * 现在chatter.Member和 myFace.Member和是不同的类 * 你不可以将其中一个member添加到另外一个member */ val fred = chatter.join("Fred") val banery = myFace.join("Banery") //这样是有问题的 fred.contacts += banery}
如果要解决这个问题,可以使用类型投影:
类型投影的目的是将外部类定义的方法中,他可以接收任意外部类对象的内部类。
也就是说newchatter.Member 和 new myFace.Member()虽然是属于不同的类,但是他们有着共同父类NetWork#Member,我们对之前的代码稍加改造:
class NetWork { class Member(val name:String){ val contacts = new ArrayBuffer[NetWork#Member]() } private val members = new ArrayBuffer[NetWork.this.Member] def join(name:String) = { val m = new Member(name) members += m m }}
三 类型别名
对于复杂的类型,你可以使用type关键字创建一个简单的别名,就像这样:
四 结构类型
结构类型利用反射机制为静态语言添加动态性,从而使得参数类型不受限于某个已命名的类型,比如:
class StructType { /** * 1 语法:def 函数名(变量名:{抽象函数},其他参数列表) * 2 {抽象函数}就表示结构体 * 3 结构体还可以使用type关键字声明 type func = {抽象函数} * 4 在函数体内就可以调用=> 变量名.抽象函数() * 5 在调用主题函数的时候,需要使用new {抽象函数的实现} * 6 所以感觉上结构体也是一个特殊的类 */ def appendLines(target:{def append(line:String):Any},lines:Iterable[String]): StringBuilder ={ val sb = new StringBuilder() for (l <- lines){ val s = target.append(l) sb.append(s).append("\n") } sb }}object Test1 extends App{ val st = new StructType val animals = List("tiger","lions","hadoop") val sb = st.appendLines(new {def append(line:String):Any = {"<"+line.toUpperCase()+">"}},animals) sb.foreach(e => print(e))}
<TIGER>
<LIONS>
<HADOOP>
另外结构体还可以使用type关键字声明:
class StructType { type append_func = {def append(line:String):Any} def appendLines(target:append_func,lines:Iterable[String]): StringBuilder ={ val sb = new StringBuilder() for (l <- lines){ val s = target.append(l) sb.append(s).append("\n") } sb }}object Test1 extends App{ val st = new StructType val animals = List("tiger","lions","hadoop") val sb = st.appendLines(new {def append(line:String):Any = {"<"+line.toUpperCase()+">"}},animals) sb.foreach(e => print(e))}
五 复合类型
语法格式: T1 with T2with T3
其中T1,T2,T3是类型,要想成为该复合类型的实例,某一个值必须满足每一个类型要求才行,因此这样的类型也被称作为交集类型
你可以用复合类型来操纵那些必须提供多个特质的值,比如:
class A { def show(desc:String): Unit ={ println(desc) }}trait B { def toUpper(message:String):String}/** * 现在这个类就是A和Serializable的复合类型 * 注意: * with 必须是trait或者java的接口,不能是scala的类或者java类 * 就算是抽象类也不行 */class ComplexType extends A with java.io.Serializable with B { override def toUpper(message: String): String = { message.toUpperCase() }}
我们可以利用关键字type声明一个复合类型
class ComplexType { type Type = A with java.io.Serializable with B def func(t:Type): Unit ={ t.show("I love you") }}
六 中置类型
中置类型是一个带有两个类型参数的类型,以中置语法表示,类型名称写在两个类型参数之间,举例来说,你可以这样写:
String Map Int 而不是Map[String,Int]
case class InfixType[S,T](val name:S,val age:T) {}object InfixType extends App{ //我么一般这么写: val infix1:InfixType[String,Int] = InfixType[String,Int]("Infix",28) //使用中置表达式写法 val infix2:String InfixType Int = InfixType("Infix",28)}
七 存在类型
存在类型的语法 [类型表达式] forsome {type T}
forSome使得我们能够使用更加复杂的关系,比如Map[T,S]
forSome {type T;type S <: T},而不仅限于类型通配符能表达的那些
class ExistsType { def func1[T](ele:Array[T] forSome {type T}):Unit = { ele.foreach(e => print(e+" ")) } def func2(ele:Array[_]):Unit = { ele.foreach(e => print(e+" ")) } //Map[_,_]相当于Map[T,U] forSome {type T;type U} def func3[T,S](dict:Map[T,S] forSome {type T;type S}): Unit ={ for((k,v) <- dict){ print(k,v) } } def func4(dict:Map[_,_]): Unit ={ for((k,v) <- dict){ print(k,v) } }}
八 自身类型
我么知道,我们可以限制混入特质的时候,限定类型。
通过语法this:指定类型 => 然后指定所允许混入的类或者其子类才可以混入该trait
class BaseTypeclass ParentTypetrait MyTrait { /** * 指定该trait只能被BaseType的子类可以混入 * 不是BaseType的子类是不可以混入这个trait的 */ this:BaseType =>}class ConcreteType extends BaseType with MyTrait/*所以这里会报错*/class ImplementType extends ParentType with MyTrait
九 抽象类型
抽象类型:是指在类或者特质中利用type关键字定义一个没有确定类型的标识,该标志在子类被确定,称这种类型为程序类型,比如:
abstract class Persons{ //声明一个未被确定的类型 type UndefinedType def show(x:UndefinedType)}class Students extends Persons{ //确定抽象类型 type UndefinedType = String def show(x:UndefinedType):Unit = { println("Student show => "+ x.toLowerCase()) }}class Teachers extends Persons{ type UndefinedType = mutable.HashMap[String,String] def show(x:UndefinedType):Unit = { for ((k,v) <- x){ println("Teacher show key => "+k+" value=>"+v) } }}object AbstractType extends App { val message = "Welcome You, Guys" val map = mutable.HashMap(("Nicky", "Math"), ("Allice", "History"), ("Judy", "English")) val s = new Students s.show(message) val t = new Teachers t.show(map)}
上述代码的也可用泛型进行实现,如:
abstract class People[T]{ def show(x:T)}class Worker extends People[String]{ def show(x:String):Unit = { println("Student show => "+ x.toLowerCase()) }}class Leader extends People[mutable.HashMap[String,String]]{ def show(x:mutable.HashMap[String,String]):Unit = { for ((k,v) <- x){ println("Teacher show key => "+k+" value=>"+v) } }}
结论:
在实际应用中,如果类型是在实例化的时候给定的,推荐用类型参数进行类的定义;如果类型是在子类型中才被确定,则推荐使用抽象类型。
- scala高级类型
- scala 高级类型
- scala 高级类型
- scala高级类型
- Scala课堂-6-高级类型
- scala简要:高级函数和高级类型
- Scala入门之高级类型:类型投影
- Scala入门之高级类型:结构类型
- Scala School 笔记(五)--高级类型
- Scala入门之高级类型:this.type
- 快学Scala第18章----高级类型
- Scala高级特性中的类型参数总结(1)
- 快学Scala 第18章高级类型练习题
- Scala 类型
- Scala类型
- 快学Scala学习笔记及习题解答(17-18类型参数与高级类型)
- scala高级编程
- Scala list高级使用
- Linux tar命令
- 回调函数
- Spring Boot持续集成测试 There are no tests to run
- PHP的分布式跟踪的一些心得
- 职场必杀技之职场礼仪
- scala 高级类型
- 如何实现SecureCRT通过密钥远程连接linux服务器
- poj2240
- 二路插入排序
- 常用的预定义和预编译
- js刷新
- angular中控制器(controller)之间传递参数的方式
- java中XML的解析
- zoj 1015