交集类型 - 更多细节
语法
从语法上讲,类型 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
从上面的规则可以看出,&
是可交换的:对于任何类型 A
和 B
,A & B <: B & A
。
B <: B A <: A
---------- -----------
A & B <: B A & B <: A
---------------------------
A & B <: B & A
换句话说,A & B
与 B & 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
的擦除类型是 S
和 T
的擦除类型的擦除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
子句中不同)的使用将在将来被弃用并删除。
本文档