Link Search Menu Expand Document

语法

语法上,类型 S & T 是一个中缀类型,中缀操作符为 &。操作符 & 是一个普通的标识符,具有普通的优先级, 并遵循寻常的解析规则。除非被另一个定义遮蔽,否则它将被解析为类型 scala.&,它充当交集类型内部表示形式的类型别名。

Type              ::=  ...| InfixType
InfixType         ::=  RefinedType {id [nl] RefinedType}

子类型规则

T <: A    T <: B
----------------
  T <: A & B

    A <: T
----------------
    A & B <: T

    B <: T
----------------
    A & B <: T

根据上面的规则,我们可以证明 &可交换的:对于任意类型 ABA & B <: B & A

   B <: B           A <: A
----------       -----------
A & B <: B       A & B <: A
---------------------------
       A & B  <:  B & A

换句话说,A & BB & A 是相同的类型,即它们有相同的值并且互为子类型。

如果 C 是一个类型构造器,则 C[A] & C[B] 可以使用下面三个规则进行简化:

  • 如果 C 是协变的,C[A] & C[B] ~> C[A & B]
  • 如果 C 是逆变的,C[A] & C[B] ~> C[A | B]
  • 如果 C 是不变的,则发生一个编译时错误

C 是协变的,可以这样推导出 C[A & B] <: C[A] & C[B]

    A <: A                  B <: B
  ----------               ---------
  A & B <: A               A & B <: B
---------------         -----------------
C[A & B] <: C[A]          C[A & B] <: C[B]
------------------------------------------
      C[A & B] <: C[A] & C[B]

C 是逆变的,可以这样推导出 C[A | B] <: C[A] & C[B]

    A <: A                        B <: B
  ----------                     ---------
  A <: A | B                     B <: A | B
-------------------           ----------------
C[A | B] <: C[A]              C[A | B] <: C[B]
--------------------------------------------------
            C[A | B] <: C[A] & C[B]

擦除

S & T 的擦除类型是 ST 擦除类型的擦除glb(最大下限)。交集类型的擦除规则以伪代码的形式给出如下;

|S & T| = glb(|S|, |T|)

glb(JArray(A), JArray(B)) = JArray(glb(A, B))
glb(JArray(T), _)         = JArray(T)
glb(_, JArray(T))         = JArray(T)
glb(A, B)                 = A                     if A extends B
glb(A, B)                 = B                     if B extends A
glb(A, _)                 = A                     if A is not a trait
glb(_, B)                 = B                     if B is not a trait
glb(A, _)                 = A                     // use first

上文中,|T| 表示 T 的擦除类型,JArray 指 Java 数组类型。

另请参见:TypeErasure#erasedGlb.

与复合类型(with)的关系

交集类型 A & B 取代了 Scala 2 中的复合类型 A with B。目前语法 A with B 仍被允许,并被解释为 A & B,但是它作为类型的用法(而不包括在 new 或者 extends 中的用法)将被弃用和删除。