泛型介绍:泛型用于指定方法或类能够接受任意类型参数,参数在实际使用时才被肯定,泛型能够有效 地加强程序的适用性,使用泛型可使得类或方法具备更强的通用性。泛型的典型应用场景 是集合及集合中的方法参数。
泛型方法:指定方法能够接受任意类型参数。
泛型类:指定类能够接受任意类型参数。
例:markdown
object GenericTypeTest01 { def main(args: Array[String]): Unit = { println(new Student11[String,Int]("黄渤",33).name) println(new Student12[String,Int]("zs",18).name) println(new Student22[String,Int]("zs",8).age) } } class Student12[T,S](var name:T,var age:S){} class Student11[T,S](var name:T, var age:S){} class Person11[T](var name:T) class Student22[T,S](name:T,var age:S) extends Person11(name) {}
类型变量界定是指在泛型的基础上,对泛型的范围进行进一步的界定,从而缩小泛型的具体范围。
例:ide
object Test01 { def main(args: Array[String]): Unit = { var generic=new Generic val result: Int = generic.compare("aa","bb") } } class Generic{ /** *T<:Comparable 表示compare方法中若是输入的类型处于Comparable类对应的继承体系中,则是合法的,不然编译不经过 * 做用是:当调用泛型的方法是,可是不知道这个泛型是否有这个方法,此时使用泛型的类型变量界定,缩写范围,使得,泛型中有这个方法 */ def compare[T<:Comparable[T]](first:T,second:T)={ val result=if(first.compareTo(second)>0) 1 else 0 result } }
类型变量界定创建在类继承的层次上,但有时候这种限定不能知足实际要求,若是但愿跨越类继承层次结构时,可使用视图界定来实现,原理是经过隐式转换来实现。
隐含参数和方法也能够定义隐式转换,称做视图。视图的绑定从另外一个角度看就是 implicit 的转换。其实视图的绑定就是为了更方便的使用隐式转化,视图界定利用<%符号来实现。
例:scala
object Test01 { def main(args: Array[String]): Unit = { var ann1 = new Animals("zs", "18") var ann2 = new Animals("zs", 18) } } case class Animals[T, S <: Comparable[S]](var name: T, var age: S)
此时若是在[T, S <: Comparable[S]]使用<:的话,在运行的时候会报错
由于:在类型变量界定的使用,默认的只能界定的类的是继承体系中的一员才成立,若是是使用隐式转换的方式默认不成立。上面代码:String类继承了Comparable,可是Int没有继承Comparable,只是隐式的将Int转换成了RichInt,RichInt继承了Comparable,因此此处出现了错误。
若是想隐式转换也能够经过泛型的话能够:3d
object Test01 { def main(args: Array[String]): Unit = { var ann1 = new Animals("zs", "18") var ann2 = new Animals("zs", 18) } } case class Animals[T, S <% Comparable[S]](var name: T, var age:
利用<%号对泛型 S 进行限定,它的意思是 S 能够是 Comparable 类继承层次结构中实现了 Comparable 接口的类,也能够是可以通过隐式转换获得的实现了 Comparable 接口的类。
code
在指定泛型类型时,有时须要界定泛型类型的范围,而不是接收任意类型。好比,要求某个 泛型类型,必须是某个类的子类,这样在程序中就能够放心的调用父类的方法,程序才能正 常的使用与运行。此时,就可使用上下边界 Bounds 的特性; Scala 的上下边界特性容许泛型类型是某个类的子类,或者是某个类的父类。
U>:T这是类型下界的定义,也就是 U 必须是类型 T 的父类(或自己,本身也能够认为是本身的父 类)。
S<:T这是类型上界的定义,也就是 S 必须是类型 T 的子类(或自己,本身也能够认为是本身的子 类)。
上界:对象
class Generic2{ //指定上界,T必须是Comparable的子类或者是Comparable def compare[T<:Comparable[T]] (first:T,second:T) ={ } }
下界:blog
class Generic3{ //指定下界,T必须是Comparable的父类或者是Comparable def compare[T>:Comparable[T]] (first:T,second:T) ={ } }
object Test01 { def main(args: Array[String]): Unit = { var list1:MyList[Person]=new MyList(new Person) var list2:MyList[Son]=new MyList(new Son) list1=list2 } } class Person class Son extends Person class MyList[+T](val value:T)
这种方式,在list中只能将子类转化成为父类的list,若是在转变以后,这个list中也只能存放子类的类型对象。协变的性质:输入的类型必须是 Son 的超类。继承
逆变
逆变定义形式如:trait List[-T]{}
当类型 B 是类型 A 的子类型,则 Queue[A]反过来能够认为是 Queue[B}的子类型。也就是被参数化类型的泛化方向与参数类型的方向是相反的,因此称为逆变(contravariance)。接口