抽象類型,例如特質和抽象類別,反過來也可以有抽象類型成員。這表示具體實作會定義實際類型。以下是一個範例
trait Buffer {
type T
val element: T
}
trait Buffer:
type T
val element: T
我們在此定義了一個抽象 類型 T
。它用來描述 元素
的類型。我們可以在抽象類別中延伸這個特質,為 T
新增一個上層類型邊界,以使其更具體。
abstract class SeqBuffer extends Buffer {
type U
type T <: Seq[U]
def length = element.length
}
abstract class SeqBuffer extends Buffer:
type U
type T <: Seq[U]
def length = element.length
請注意,我們如何能在 T
的上層類型邊界規格中使用另一個抽象類型 U
。這個 類別 SeqBuffer
讓我們能夠透過聲明類型 T
必須是新抽象類型 U
的 Seq[U]
子類型,來儲存緩衝區中的序列。
具有抽象類型成員的特質或 類別 通常與匿名類別實例化結合使用。為了說明這一點,我們現在來看一個處理參考整數清單的序列緩衝區的程式
abstract class IntSeqBuffer extends SeqBuffer {
type U = Int
}
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
new IntSeqBuffer {
type T = List[U]
val element = List(elem1, elem2)
}
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
abstract class IntSeqBuffer extends SeqBuffer:
type U = Int
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
new IntSeqBuffer:
type T = List[U]
val element = List(elem1, elem2)
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
在這裡,工廠 newIntSeqBuf
使用 IntSeqBuffer
的匿名類別實作(即 new IntSeqBuffer
)來設定抽象類型 T
為具體類型 List[Int]
。
也可以將抽象類型成員轉換為類別的類型參數,反之亦然。以下是僅使用類型參數的上述程式碼版本
abstract class Buffer[+T] {
val element: T
}
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
def length = element.length
}
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
new SeqBuffer[Int, List[Int]] {
val element = List(e1, e2)
}
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
abstract class Buffer[+T]:
val element: T
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T]:
def length = element.length
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
new SeqBuffer[Int, List[Int]]:
val element = List(e1, e2)
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
請注意,我們必須在這裡使用 變異註解(+T <: Seq[U]
),才能隱藏從方法 newIntSeqBuf
傳回的物件的具體序列實作類型。此外,有些情況無法將抽象類型成員替換為類型參數。