本文共 4473 字,大约阅读时间需要 14 分钟。
==> 泛型类
---> T 可以代表任意类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Person[T]{ private var name : T = _ def setName(name : T) = { this .name = name} def getName() : T = { this .name} } // ***********测试***************** object Person{ def main(args : Array[String]) : Unit = { var p = new Person[String]() p.setName( "hello" ) println(p.getName()) } } |
==> 泛型函数
---> 类型参数放在方法名之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //* 泛型函数 // 创建一个固定类型的数组 // 普通函数 def mkInt(elems : Int*) = Array[Int](elems :_ *) def mkString(str : String*) = "mkString" // 使用泛型函数,可以接收任意类型 def mkArray[T : ClassTag](elems : T*) = Array[T](elems :_ *) // ***********测试***************** // 普通函数只能传入相对应类型的参数 mkInt( 1 , 2 , 3 ) mkString( "hello" , "world" ) // 泛型函数可以传入任意类型的参数 mkArray( 11.26 , 665 , 84 , "hello" ) |
==> 类型的上界和下界(Upper Bounds 和 Lower Bounds)
---> 用来定义泛型变量的范围 :
---> S <: T (上界) S 必须是 T 类型的子类或类本身
1 2 3 4 5 6 7 8 9 10 | class Person 1 { def gender() = {println( "gender" )} } class Man extends Person 1 { override def gender() = {println( "man" )} } class Women extends Person 1 { override def gender() = {println( "women" )} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | object UpperBoundsAndLowerBounds { // 定义一个泛型函数,通过上界的方式指定泛型的范围必须是 Person1 的子类或者Person1 类,并调用类中的 gender 方法 def getGender[T < : Person 1 ](g : T) = {g.gender()} def main(args : Array[String]) : Unit = { // 创建一个Person1 对象 ,调用getGender 方法调用 Personal 中的 gender 方法 var p : Person 1 = new Person 1 getGender(p) // 创建一个 Man 对象 ,通过 getGender 方法调用Man 类中的 gender 方法 var m = new Man getGender(m) } } |
---> U >: T(下界) U 必须是 T 类型的父类或类本身,此处不作示例,与上面例子类似,只是传入 getGender 方法中的参数必须是 Person1 类或其父类的对象
==> 视图界定 <%
---> 与类型的上界相似,但是比类型的上界适用范围更广,除了所有的子类与类本身,它还允许通过隐式转换得到的类型
1 2 3 4 5 6 7 8 | def int 2 String[T < % String](x : T, y : T) = { println(x + "*****" + y) } // ***********测试***************** int 2 String( "hello" , "world" ) implicit def int 2 String 1 (n : Int) : String = {n.toString} int 2 String( 100 , 120 ) |
==> 协变和逆变
---> 协变: 泛型变量的值可以是子类或类本身 在类型参数前加一个 “+” 符号 子类转换为父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //* 协变和逆变 在类型的前面加入 +号,就可以使类的特征变为协变了 // 将子类对象转换为父类对象称为协变 + // 将父类对象转换为子类对象称为逆变 - package demo 1 { // 父类 class Animal{} // 子类 class Bird extends Animal class Sparrow extends Bird // 吃东西的类 协变 class EatSomethings[+T](t : T){} // ***********测试***************** object Demo 1 { def main(args : Array[String]) : Unit = { // 创建一个吃东西的对象 var c 1 : EatSomethings[Sparrow] = new EatSomethings[Sparrow]( new Sparrow) var c 2 : EatSomethings[Animal] = c 1 } } } |
---> 逆变: 泛型变量的值可以是父类或类本身 在类型参数前加一个 “ - ” 符号 父类转换为子类 例:省略
==> 隐式转换函数
---> 以关键字 implicit 申明
---> 单个参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Fruit(name : String){ def getFruitName() : String = {name} } class Monkey(f : Fruit){ def say() = {println( "Monkey like " + f.getFruitName()) } } // ***********测试***************** object ImplicitDemo { def main(args : Array[String]) : Unit = { var f : Fruit = new Fruit( "bnanan" ) // 调用 fruit 的方法,希望 Monkey这个say 方法来实现 // 需要将 fruit 的对象转换为 monkey 对象, 即定义一个隐匿转换函数 implicit def fruit 2 Monkey(f : Fruit) : Monkey = { new Monkey(f)} // 将 fruit 对象转换为 Monkey 对象 // 调用Monkey中的 say 方法 f.say() } } |
==> 隐式参数 使用 implicit 关键字申明的函数参数
---> 可以使用隐式参数进行类型转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 隐式参数 def testParam( implicit name : String) = {println( "The value is " + name)} implicit val name : String = "这是一个隐式值" // ***********测试***************** testParam //--------------------------------------------------------------- // 带隐式参数的泛型函数 // Ordered[T] 使类型可排序, // 原型:def smaller // (implicit order:T => Ordered[T]) def smaller[T](a : T, b : T)( implicit order : T = > Ordered[T]) = if (order(a) < b) a else b // ***********测试***************** smaller( 100 , 56 ) smaller( "hello" , "hi" ) |
==> 隐式类 对类 增加 implicit 限定 的类,其主要作用就是对类的功能增强
---> 编写一个隐式类,使类实现更多的功能
1 2 3 4 5 6 7 8 9 10 11 12 | object testImplicit { // 定义一个隐式类 implicit class Calc(x : Int){ def add(a : Int) : Int = a + x } // ***********测试***************** def main(args : Array[String]) : Unit = { println( "两个数字的和:" + 1 .add( 2 )) } } |
---> 程序过程分析:
--- 当 1.add(2)时,scala 的编译器不会报错,在当前域中查找,有没有 implicit 修饰的,同时可以将 Int 作为参数的构造器,并且具有 add 方法的类,通过查找,找到 Calc
--- 利用隐式类 Calc 来执行 add 方法
==> 个人总结:
---> 通过泛型,可以使我们定义一个模具,就像蛋糕的模具,我们可以分别放入草莓,蓝莓等不同的原料加工出不同口味的蛋糕来
---> 通过使用 上界,下界,视图界定,协变,逆变,对泛型的范围制定规则,使我们可以传入的符合规则的参数
---> 隐式函数,隐式参数,隐式类,会在程序运行时首先被查找,若有符合 以 implicit 修饰的参数,函数以及类,先执行,然后才运行程序
若总结有误,还请多多指教,谢谢!!!
转载地址:http://jpkra.baihongyu.com/