-
可以用类型参数来定义变量,方法参数和返回值类型
-
带有一个或多个类型参数的类称为泛型
-
T和S均为类型参数
class Pair[T,S](val first : T,val second : S)
-
泛型函数
-
函数和方法也可以带类型参数
def getMiddle[T](a : Array[T]) = a(a.length/2)
-
类型变量界定
-
添加上界 T<:Comparable[T] 这意味着T必须是Comparable[T]的子类型
class Pair[T <:Comparable[T]](val first : T ,val second : T){ def smaller = if (first.compareTo(second) <0 ) first else second }
-
添加下届 R >: T R为T的超类
class Pair[T <:Comparable[T]](val first : T ,val second : T){
def replaceFirst[R >: T](newFirst : R) = new Pair[R](newFirst,second)
}
- 视图界定
- <%关系意味着T可以被隐式转换成Comparable[T]
- 视图界定T<%V要求必须存在一个从T到V的隐式转换
class Pair[T <% Comparable[T]]
-
上下文界定(TODO)
-
上下文界定的形式为T:M 其中M是另一个泛型类,要求必须存在有一个类型为M[T]的"隐式值"
-
Manifest上下文界定
-
要实例化一个泛型Array[T],需要一个Manifest[T]对象
def makepair[T : Manifest](first : T ,second : T){
val r = new Array[T](2)
r[0] = first
r[1] = second
r
}
- 如果传入makepair(4,5) 将构建一个int数组
多重界定
- 类型变量可以同时有上界和下界
- T >: Lower <: Upper
- 不能同时有多个上界或多个下界
- 一个类型可以实现多个特质
- T <: Comparable[T] with Serializable with Cloneable
- 可以有多个视图界定
- T <% Comparable[T] <% String
- 可以有多个上下文界定
- T : Ordering : Manifest
类型约束
- T =:= U 测试T是否等于U
- T <:< U 测试T是否是U的子类
- T <%< U 测试T能否被隐式转换为U
- 如下例子 只有在调用smaller是并且构造的参数符合T <:< Ordered[T] 才会执行
class Pair[T](val first :T, val second :T){
def smaller(implicit env :T <:< Ordered[T]){
if (first < second ) first else second
}
}
- 另一个用途是改进类型推断
- 如下情况无法推断出A的类型
def firstLast[A,C <: Iterable[A]](it : C) = (it.head,it.last)
- 如下写法可以先匹配出C的类型 再根据C来匹配出A的类型
def firstLast[A,C](it : C)(implicit ev : C <:< Iterable[A]) =(it.head,it.last)
协变
class Pair[+T](val first :T,val second :T)
- +意味着该类型与T协变 与T按同样的方向型变 如果Student是Person的子类 那么Pair[Student]也是Pair[Person]的子类
逆变
-
类型变化的方向与子类型方向是相反的.Student是Person的子类型,但Friend[Student]是Friend[Person]的超类型
-
协变和逆变点
-
对于某个对象而言消费的值适合逆变,产出的结果适合协变
-
scala中数组是不支持协变的 不能将Array[Student]转换为Array[Person]
-
对象不能泛型
-
类型通配符