Parameterized Types: 参数化类型
Variance Annotations: 变型注解
类似 List[+A] 这样的声明,表示 List被一个单类型参数化,即类型A,符号 + 代表协变注解,表示List在这个类型参数中是协变的, 表现为 List[String]同样是List[Any]的子类,因为String是Any的子类.
符号 - 表示为逆变.
Type Constructors: 类型构造器
有时候会见到类型构造器被用于参数化类型.这展示了参数化类型如果创建专有(specific)类型.和 实例构造器用于创建类的实例一个道理.
比如类型List是List[String]和List[Int]的构造器,二者有作为两个不同的类型.事实上可以把所有的类叫做类型构造器,那些不带类型参数的,可以看做是带了零个类型参数的 参数化类型.
Type Parameter Names: 类型参数的名称
注意为你的类型参数使用描述性的名字.
一些简单的命名规则:
- 为非常通用的类型参数,使用A,B,T1,T2等单字母或双字母的名字.
- 对那些与容器密切相关的类型使用更具描述性的名称.
Type Bounds: 类型边界
在定义参数化类型或方法时,必须要为类型参数指定类型边界(bound).比如容器可能假设某些方法存在于类型参数对应的所有类型中.
Upper Type Bounds: 上界
上界指一个类型必须是另一个类型的子类型.
A <: AnyRef
,表示任何A都是AnyRef的子类型.A也可以是AnyRef本身.
需要注意的是,类型边界和型变是两个不想关的问题.类型边界对参数化类型所允许采用的类型做了限制,比如: T <: AnyRef
约束T必须是AnyRef的子类型.型变表示参数化类型的子类实例是否可以替换父类实例,比如,List[+T]
是协变的,所以List[String]是List[Any]的子类型.
Lower Type Bounds: 下界
下界指一个类型必须是另一个的父类型.
比如Option的getOrElse方法:
sealed abstract class Option[+A] extends Product with Serializable {
...
@inline final def getOrElse[B >: A](default: => B): B = {...}
...
}
如果该Option实例是Some(A),则返回容器中的值.否则参数default被求值并返回,它必须是A的父类型.
class Parent(val value: Int) { // 1
override def toString = s"${this.getClass.getName}($value)"
}
class Child(value: Int) extends Parent(value)
val op1: Option[Parent] = Option(new Child(1)) // 2 Some(Child(1))
val p1: Parent = op1.getOrElse(new Parent(0)) // Result: Child(1)
val op2: Option[Parent] = Option[Parent](null) // 3 None
val p2a: Parent = op2.getOrElse(new Parent(10)) // Result: Parent(10)
val p2b: Parent = op2.getOrElse(new Parent(100)) // Result: Parent(100)
val op3: Option[Parent] = Option[Child](null) // 4 None
val p3a: Parent = op3.getOrElse(new Parent(20)) // Result: Parent(20)
val p3b: Parent = op3.getOrElse(new Child(200)) // Result: Child(200)
- 定义一个简单的类型继承
- 因为class Option[+A],即Option为协变,Option[Parent]同样是Option[Child]的父类.
- OptionX总会返回None,引用返回类型为Option[Parent]
- 同样为None,引用返回类型Option[Child],和应用返回类型Option[Parent]一样