Simple Scala: Type System

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: 类型参数的名称

注意为你的类型参数使用描述性的名字.

一些简单的命名规则:

  1. 为非常通用的类型参数,使用A,B,T1,T2等单字母或双字母的名字.
  2. 对那些与容器密切相关的类型使用更具描述性的名称.

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)
  1. 定义一个简单的类型继承
  2. 因为class Option[+A],即Option为协变,Option[Parent]同样是Option[Child]的父类.
  3. OptionX总会返回None,引用返回类型为Option[Parent]
  4. 同样为None,引用返回类型Option[Child],和应用返回类型Option[Parent]一样

Context Bounds: 上下文边界

View Bounds: 视图边界

Understanding Abstract Types