在 GitHub 上编辑此页面

交集类型 - 更多细节

语法

从语法上讲,类型 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[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,但它作为类型(与在 newextends 子句中不同)的使用将在将来被弃用并删除。