泛型类是以类型作为参数,Scala类型参数放在方括号[]
中,Java放在<>
中
变型 Variance
Scala与Java一样,普通泛型类型都是不变的(invariant)
Scala支持对泛型类的类型参数添加变化型注释,使得他们是协变的(covariant),逆变的(contravariant)
- 协变Covariance:
A
是B
的子类,List[A]
是List[B]
的子类 - 逆变Contravariance:对于类
class C[-A]
,A
是B
的子类,C[B]
是C[A]
的子类 - 不变Invariance:
C[B]
和C[A]
没有任何关系
class C[+A] // A covariant class
class C[-A] // A contravariant class
class C[A] // An invariant class
对trait Function1[-T, +R]
的理解
Scala标准库中Function1
代表具有一个参数的函数,参数类型为T
,第二个参数类型R
表示返回类型。
Function1
对它的参数类型来说是逆变,对返回类型来说是协变的(实际上所有函数都是这样的),函数字面量 A => B
表示为 Function1[A, B]
举例:
Animal => Mouse
是Cat => SmallAnimal
的子类型
abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
abstract class SmallAnimal extends Animal
case class Mouse(name: String) extends SmallAnimal
Java数组具有协变性,泛型具有不变型(标准库中List<Object>和List<String>
无关)
//Java代码,可以编译通过,运行抛出异常 java.lang.ArrayStoreException
Integer[] integer = new Integer[3];
Object[] objectsArray = integer;
objectsArray[0] = "dfg";
System.out.println(objectsArray[0]);
Scala数组类型是不变的,为了与Java数组的兼容,可以进行类型转换,转化为参数类型的任何父类型
scala> val a1 = Array("abc")
a1: Array[String] = Array(abc)
scala> val a2: Array[Object] = a1.asInstanceOf[Array[Object]] //不能直接复制,类型不同
a2: Array[Object] = Array(abc)
类型边界
不允许使用+
号注解的类型参数作为方法的参数类型,此外由于可变字段var
会自动产生setter方法,所以可变字段的类型也不能是协变类型,可以通过函数边界解决这个问题
//错误的代码
class Cell[+T](init: T) {
private[this] var current = init
def get = current
def set(x: T) = { current = x } //编译错误 covariant type T occurs in contravariant position in type T of value x
}
[B <: A]
上界upper bound:表示类型参数B
对应类型为A
的子类,类似于Java的<? extends A>
[B >: A]
下界lower bound:表示类型参数或抽象类型B
对应类型为A
的超类型,通常应用于A为协变类型,设定下界,B作为方法的类型参数
Java可以通过通配符实现变性
上界限定<? extends A>
,实现了协变性,作为返回类型,或者类型参数
下界限定<? super A>
,实现逆变性,作为输入类型
术语 | Scala | Java |
---|---|---|
Parametrized type | List[String] | List<String> |
Actual type parameter | String | String |
Generic type | List<A> | List<E> |
Formal type parameter | A | E |
Unbounded wildcard type | List[_] | List<?> |
Raw type | List | List |
Type parameter with lower bound | [A >: Number] | <E super Number> |
Type parameter with upper bound | [A <: Number] | <E extends Number> |
Wildcard type with lower bound | [_ >: Number] | <? super Number> |
Wildcard type with upper bound | [_ <: Number] | <? extends Number> |
Recursive type bound | [A <: Ordered[A]] | <T extends Comparable<T>> |
Type constructor | List, constructs List[Int] etc | Same as in Scala |
Variance annotation | + or - i.e. [+A] or [-A] | not supported |
Covariance annotation | + i.e. [+A] | not supported |
Contravariance annotation | - i.e. [-A] | not supported |
网友评论