有時有必要表達物件的類型是其他多種類型的子類型。
在 Scala 中,這可以用交集類型(或 Scala 2 中的複合類型)來表達,它們是像交集任何部分一樣運作的類型。
假設我們有兩個特質 Cloneable
和 Resetable
trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = { // makes clone public
super.clone().asInstanceOf[Cloneable]
}
}
trait Resetable {
def reset: Unit
}
trait Cloneable extends java.lang.Cloneable:
override def clone(): Cloneable = // makes clone public
super.clone().asInstanceOf[Cloneable]
trait Resetable:
def reset: Unit
現在假設我們要撰寫一個函式 cloneAndReset
,它會取得一個物件,複製它,並重設原始物件
def cloneAndReset(obj: ?): Cloneable = {
val cloned = obj.clone()
obj.reset
cloned
}
def cloneAndReset(obj: ?): Cloneable =
val cloned = obj.clone()
obj.reset
cloned
問題來了,參數 obj
的類型是什麼。如果是 Cloneable
,則可以複製物件,但無法重設;如果是 Resetable
,我們可以重設它,但沒有複製操作。為避免在這種情況下進行類型轉換,我們可以將 obj
的類型指定為 Cloneable
和 Resetable
。
此複合類型在 Scala 中寫成 Cloneable with Resetable
。
以下是更新後的函數
def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
//...
}
請注意,你可以有超過兩種類型:A with B with C with ...
。這與 (...(A with B) with C) with ... )
的意思相同
此交集類型在 Scala 中寫成 Cloneable & Resetable
。
以下是更新後的函數
def cloneAndReset(obj: Cloneable & Resetable): Cloneable = {
//...
}
請注意,你可以有超過兩種類型:A & B & C & ...
。而且 &
是結合的,因此可以在任何部分加上括號而不會改變其意義。