1. 泛型类
泛型类就是在类的声明中,定义一些泛型类型。然后类内部的字段或者方法就可以使用这些泛型类型
使用泛型类通常是需要对类中的某些成员(字段、方法中的参数或变量)进行统一的类型限制,这样可以保证程序更好的健壮性和稳定性
如果不使用泛型进行统一的类型限制,那么在后期程序运行过程中,难免会出现问题,比如传入了不希望的类型,导致程序出问题
在使用类的时候,比如创建类的对象,将类型参数替换为实际类型即可
scala自动推断泛型类型特性即直接给使用了泛型类型的字段赋值时,scala会自动进行类型推断
泛型类型与泛型类类似,可以给某个函数在声明时指定泛型类型,然后在函数体内的多个变量或者返回值之间就可以使用泛型类型进行声明,从而对某个特殊的变量或者多个变量进行强制的类型限制。
与泛型类一样你可以通过给使用了泛型类型的变量传递值让scala自动推断泛型的实际类型,也可以在调用函数时手动指定泛型类型
1.1 类中的范型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class GenericDemo1 [T1 ,T2 ](var name:T1 ) { private var v:T1 = _ def setV (v1:T1 ) = { v = v1 } def getV = v var age :T2 = _ def say ()= { println(s"hello $name " ) } } object GenericDemo1 extends App { val c1 = new GenericDemo1 [String ,Int ]("小明" ) c1.say() c1.age = 12 println(s"${c1.name} age is ${c1.age} " ) c1.setV("value" ) println(c1.getV) val c2 = new GenericDemo1 [Int ,String ](123 ) c2.setV(123 ) println(c2.getV) }
1.2 函数中的泛型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 object ClassDemo02 { def main (args: Array [String ]): Unit = { val c01 = ClassDemo02 println(say[String ,Int ,String ]("小明" ,12 )) } def say [T1 ,T2 ,B1 ](name:T1 ,age:T2 ):B1 ={ (name+"<=>" +age).asInstanceOf[B1 ] } } object GenericDemo2_1 extends App { def say [T1 ](value:T1 ):Unit ={ println(s"value.getClass = ${value.getClass} " ) println(s"value is $value " ) } say[String ]("小明" ) say[Int ](12 ) say(0.12 ) }
1.3 泛型定义type 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 object GenericDemo3 { def main (args: Array [String ]): Unit = { println(m1("xiaom" ).name) println(m2(List (1 ,2 ,3 ,4 ,5 )).len) } def m1 (name1:String ) = new GenericDemo3_1 { type T = String val name = name1 } def m2 (e1:List [Int ]) = new GenericDemo3_2 { type T = Int val list = e1 } } abstract class GenericDemo3_1 { type T val name:T } abstract class GenericDemo3_2 { type T val list:List [T ] def len = list.length }
1.4 泛型定义枚举(Enum) Scala没有在语言层面定义Enumeration,而是在库中实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 object GenericDemo4 extends App { println(Color .RED ) println(Color .values) println("-----" ) val colorful = Color .values.filterNot(List ("黑色" ,"白色" ) contains _.toString) colorful.foreach(println(_)) } object Color extends Enumeration { val RED = Value ("红色" ) val GREEN = Value ("绿色" ) val BLUE = Value ("蓝色" ) val WHITE = Value ("黑色" ) val BLASK = Value ("白色" ) }
2. 上边界与下边界 2.1 上边界 上边界用来判断我传参类型最大为那个类型
上边界: <: (小于号冒号)即泛型T,只能是 GenericDemo5_2 或其子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class GenericDemo5_1 class GenericDemo5_2 extends GenericDemo5_1 class GenericDemo5_3 extends GenericDemo5_2 class GenericDemo5 [T <: GenericDemo5_2 ] { def say (p: T ) = { println(p.getClass) } } object GenericDemo5 extends App { val c5= new GenericDemo5 [GenericDemo5_2 ] c5.say(new GenericDemo5_2 ) c5.say(new GenericDemo5_3 ) val c5_3= new GenericDemo5 [GenericDemo5_3 ] c5_3.say(new GenericDemo5_3 ) }
2.2 下边界 下边界: >: (大于号冒号) 即 T 只能是 GenericDemo6_2 或其父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class GenericDemo6_1 class GenericDemo6_2 extends GenericDemo6_1 class GenericDemo6_3 extends GenericDemo6_2 class GenericDemo6 [ T >: GenericDemo6_2 ] { def say (p:T ): Unit ={ println(p.getClass) } } object GenericDemo6 extends App { val c6 = new GenericDemo6 [GenericDemo6_2 ] c6.say(new GenericDemo6_2 ) c6.say(new GenericDemo6_3 ) val c6_1= new GenericDemo6 [GenericDemo6_1 ] c6_1.say(new GenericDemo6_1 ) c6_1.say(new GenericDemo6_2 ) c6_1.say(new GenericDemo6_3 ) }
3. 协变与逆变 协变是scala中比较有特色的功能,它完美解决了java中泛型的一些缺陷
比如 P 是M 的子类, 那么 C[P] 是不是C[M] 的子类呢
在java中很遗憾不是,这给我们编码带来了很多局限性,scala的协变完美的解决了这个问题,其实协变就是泛型上边界的一种加强
3.1 协变 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class GenericDemo7_1 class GenericDemo7_2 extends GenericDemo7_1 class GenericDemo7_3 extends GenericDemo7_2 class C [+T ]class GenericDemo7 { def say (c:C [GenericDemo7_2 ]) = { println(c.getClass) } } object GenericDemo7 extends App { val c7 = new GenericDemo7 c7.say(new C [GenericDemo7_2 ]) c7.say(new C [GenericDemo7_3 ]) c7.say(new C {}) }
3.2 逆变 逆变 scala中比较有特色的功能,它完美解决了java中泛型的一些缺陷
比如 P 是M 的子类, 那么 C[P] 是不是C[M] 的子类呢
在java中很遗憾不是,这给我们编码带来了很多局限性,scala的逆变完美的解决了这个问题,
其实逆变就是泛型下边界的一种加强
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class GenericDemo8_1 class GenericDemo8_2 extends GenericDemo8_1 class GenericDemo8_3 extends GenericDemo8_2 class C [-T ]class GenericDemo8 { def say (c: C [GenericDemo8_2 ]) = { println(c.getClass) } } object GenericDemo8 extends App { val c8 = new GenericDemo8 c8.say(new C [GenericDemo8_1 ]) c8.say(new C [GenericDemo8_2 ]) c8.say(new C {}) }