泛型中的符号
符号 | 作用 |
---|---|
[T <: UpperBound] | 上界 |
[T >: LowerBound] | 下界 |
[T <% ViewBound] | 视界 |
[T : ContextBound] | 上下文界 |
[+T] | 协变 |
[-T] | 逆变 |
关于各个泛型符号的详解
1. 上下界约束符号 <: 与 >:
class MaxValue[T <: Comparable[T]](x:T,y:T){
def compare:T = if (x.compareTo(y)>0) x else y
}
例子中
MaxValue[T <: Comparable[T]]
是上届的定义,也就是T必须是Comparable的子类(或本身,自己也可以认为是自己的子类)。
同理,如果
MaxValue[T >: Comparable[T]]
就下届的定义,也就是T必须是Comparable的父类(或本身,自己也可以认为是自己的子类)。
2.view bounds(视界) 符号 <%
//视图界定:底层隐式转换了
class MaxValue2[T <% Comparable[T]](x:T,y:T){
def compare:T = if (x.compareTo(y)>0) x else y
}
它比<:
适用的范围更广,除了所有的子类型,顶层做了隐式转换,允许scala中的数据类型调用。
下面举例说明 <: 和 <:在实际使用中的差异
object UpperLowerBoundsApp {
def main(args: Array[String]): Unit = {
/**
* 我们如果直接使用 <: 来定义泛型来实现底层接口,在使用的时候会有如下问题
* val maxValue = new MaxValue[Int](10,13)
*
* Error type arguments [Int] do not conform to class MaxValue's type parameter bounds [T <: Comparable[T]]
* val maxValue = new MaxValue[Int](10,13)
*
* 报错原因:
* scala中Int的源码:final abstract class Int private extends AnyVal
* 因此 scala并没有实现Comparable接口与
*
* 但是 java 里的Integer public final class Integer extends Number implements Comparable<Integer>
* java里的Integer是按照comparable来实现的
*/
val maxValue1 = new MaxValue[Integer](10,13)
val maxValue2 = new MaxValue(Integer.valueOf(10),Integer.valueOf(13))
println(maxValue1.compare)
println(maxValue2.compare)
/**
* <: 定义的泛型,因为scala的数据类型没有实现comparable接口,不得不掉调用java底层的数据类型来实现
* 但是,在scala中,可以使用 <% 或者 >% 定义泛型,来直接在泛型中使用
* 这样能够使用scala 中的数据类型的原因是,在scala中,通过隐式转换的方式,是的 <% 既能实现comparable接口,有能兼容scala中的数据类型
*/
val maxValue3 = new MaxValue2(10,13)
println(maxValue3.compare)
}
}
/**
* 上届
* @tparam T
*/
class MaxValue[T <: Comparable[T]](x:T,y:T){
def compare:T = if (x.compareTo(y)>0) x else y
}
//视图界定:底层隐式转换了
class MaxValue2[T <% Comparable[T]](x:T,y:T){
def compare:T = if (x.compareTo(y)>0) x else y
}