Scala 導覽

泛型類別

語言

泛型類別是將型別視為參數的類別。它們對於集合類別特別有用。

定義泛型類別

泛型類別會在方括號 [] 中將型別視為參數。一個慣例是使用字母 A 作為型別參數識別碼,不過可以使用任何參數名稱。

class Stack[A] {
  private var elements: List[A] = Nil
  def push(x: A): Unit =
    elements = x :: elements
  def peek: A = elements.head
  def pop(): A = {
    val currentTop = peek
    elements = elements.tail
    currentTop
  }
}
class Stack[A]:
  private var elements: List[A] = Nil
  def push(x: A): Unit =
    elements = x :: elements
  def peek: A = elements.head
  def pop(): A =
    val currentTop = peek
    elements = elements.tail
    currentTop

這個 Stack 類別的實作將任何型別 A 視為參數。這表示底層清單 var elements: List[A] = Nil 只能儲存型別 A 的元素。程序 def push 只接受型別 A 的物件(注意:elements = x :: elementselements 重新指定為一個新的清單,方法是將 x 加到目前的 elements 之前)。

此處的 Nil 是空的 List,不要與 null 混淆。

用法

若要使用泛型類別,請將型別放入方括號中,取代 A

val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop())  // prints 2
println(stack.pop())  // prints 1
val stack = Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop())  // prints 2
println(stack.pop())  // prints 1

實例 stack 只能接受 Int。但是,如果類型參數有子類型,則可以傳遞

class Fruit
class Apple extends Fruit
class Banana extends Fruit

val stack = new Stack[Fruit]
val apple = new Apple
val banana = new Banana

stack.push(apple)
stack.push(banana)
class Fruit
class Apple extends Fruit
class Banana extends Fruit

val stack = Stack[Fruit]
val apple = Apple()
val banana = Banana()

stack.push(apple)
stack.push(banana)

類別 AppleBanana 都擴充 Fruit,因此我們可以將實例 applebanana 推送到 Fruit 的堆疊中。

注意:泛型類型的子類型是 *不變* 的。這表示如果我們有一個類型為 Stack[Char] 的字元堆疊,則無法將它用作類型為 Stack[Int] 的整數堆疊。這是不健全的,因為它會讓我們能夠在字元堆疊中輸入真正的整數。結論是,Stack[A] 僅當且僅當 B = A 時才是 Stack[B] 的子類型。由於這可能會相當具有限制性,因此 Scala 提供了一個 類型參數註解機制 來控制泛型類型的子類型行為。

此頁面的貢獻者