/**
* 泛型类、泛型函数
* 泛型用于指定方法或类可以接受任意类型参数
* 参数在实际使用时才被确定
* 泛型可以有效地增强程序的适用性
* 使用泛型可以使得类或方法具有更强的通用性
*/
object TestGeneric {
def main(args: Array[String]): Unit = {
// 泛型类
class GenericClass[F, S, T](val f: F, val s: S, val t: T)
// 实例化方式1:类型推导
val gc = new GenericClass("xj", 22, 'C')
// 实例化方式2:类型声明
val gc2 = new GenericClass[String, String, Int]("xj", "lj", 22)
// 泛型函数
def getData[T](list: List[T]) = list(list.length - 1)
println(getData(List('b', "bj", 26, 2.0)))
// 获得getData的引用,必须指定泛型类型
val t = getData[Int] _
println(t(List(1, 2, 3, 4, 5)))
// 类型变量界定
// 通过编译,为范型T增加了约束,限定上界为Comparable[T]
// 范型类型T也就具有了Comparable[T]中的compareTo(T)方法,类似于java中的继承
def typeVariable[T <: Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0)
1
else
-1
}
// 正确运行,String有上界Comparable[T]
println(typeVariable("a", "b"))
// Int类型运行错误,Int没有上界Comparable[T],但是为何编译不报错?
// 如果想成功运行的话,就需要进行一次隐式转换,
// 将Int类型转换成支持Comparable[T]的类型,此时应该改用视图界定<%
// 视图界定帮我们进行了隐式转换,将Int转换成了支持Comparable[T]的RichInt类型
// println(typeVariable(1,2))
// 视图界定
// <% 泛型视图界定符,表示把传入不是Comparable[T]类型的 隐式传换 为Comparable[T]类型
// a之所以能使用方法compareTo,是因为a被隐式传换为Comparable[T]类型
def viewBound[T <% Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0)
a
else
b
}
// Int类型被隐式转换成了支持Comparable[T]的RichInt类型
println(viewBound(1, 2))
// 上下文界定
class PairOrdering[T: Ordering](val first: T, val second: T) {
// compareTo方法进行比较,如果大于0返回first
def bigger(implicit ordered: Ordering[T]) = {
if (ordered.compare(first, second) > 0) first else second
}
}
// 函数调用
var pair = new PairOrdering("Spark", "Hadoop")
// 执行结果:Spark
println(pair.bigger)
// 多重界定
// 一个类型参数有多个类型约束,比如:
// T >: A <: B 表示T所允许的范围是A的父类 或者是B的子类
// T: A: B 表示作用域必须同时满足存在A[T]和B[T]隐式值
// T <% A <% B表示作用域必须同时满足T到A和T到B的隐式转换
class Animal{
def speak():Unit={
println("666")
}
}
class Person extends Animal{}
class Student extends Person{}
def showAll[T >: Person <: Person](str:T) ={
str.speak()
}
// Manifest关键字
// 数组在声明时必须要求指定具体的类型,在函数泛型是无法知道具体类型,
// 通过Manifest关键字使得运行时可以根据这个Manifest参数做更多的事情
def arrayMake[T: Manifest](first: T, second: T) = {
val r = new Array[T](2);
r(0) = first;
r(1) = second;
// 返回r
r;
}
// val array = arrayMake("a","b")
// for (i <- array) println(i)
arrayMake("a","b").foreach(println)
// ClassTag关键字
// ClassTag[T]保存了泛型擦除后的原始类型T,提供给被运行时的
def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
mkArray(42,13).foreach(println)
mkArray("Japan","Brazil","Germany").foreach(println)
// 类型约束
// 类型约束提供给你的是另外一个限定类型的方式,总共有三种关系可供使用
// T =:= U 表示测试T 是否等于U类型
// T <:< U 表示测试T 是否为U的子类型
// T <%< U 表示是否存在T到U 的转换
// 协变,逆变
// 协变[+T]
// 只有满足指定类型或者指定类型子类才可以被兼容,即使是指定类型的父类也不会被兼容,
// 通俗地讲,只要是你或者你的子类我都可以编译通过
// 逆变[-T]
// 只有满足指定类型或者指定类型父类才可以被兼容,即使是指定类型的子类也不会被兼容
// 通俗地讲,只要是你或者你的父类我都可以编译通过
}
}