Scala泛型

2018-03-17  本文已影响0人  wangdy12

泛型类是以类型作为参数,Scala类型参数放在方括号[]中,Java放在<>

变型 Variance

Scala与Java一样,普通泛型类型都是不变的(invariant)
Scala支持对泛型类的类型参数添加变化型注释,使得他们是协变的(covariant),逆变的(contravariant)

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 => MouseCat => 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
上一篇下一篇

猜你喜欢

热点阅读