交集類型 - 更多詳細資訊
語法
在語法上,類型 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
子句中相反),並將其刪除。
在本文中