Scala 導覽

特質

語言

特質用於在類別之間共用介面和欄位。它們類似於 Java 8 的介面。類別和物件可以延伸特質,但特質無法被實例化,因此沒有參數。

定義特質

最小的特質只包含關鍵字 trait 和一個識別碼

trait HairColor

特質在作為泛型類型和具有抽象方法時特別有用。

trait Iterator[A] {
  def hasNext: Boolean
  def next(): A
}
trait Iterator[A]:
  def hasNext: Boolean
  def next(): A

延伸 trait Iterator[A] 需要類型 A 和方法 hasNextnext 的實作。

使用特質

使用 extends 關鍵字來延伸特質。然後使用 override 關鍵字實作特質的任何抽象成員

trait Iterator[A] {
  def hasNext: Boolean
  def next(): A
}

class IntIterator(to: Int) extends Iterator[Int] {
  private var current = 0
  override def hasNext: Boolean = current < to
  override def next(): Int = {
    if (hasNext) {
      val t = current
      current += 1
      t
    } else 0
  }
}

val iterator = new IntIterator(10)
iterator.next()  // returns 0
iterator.next()  // returns 1
trait Iterator[A]:
  def hasNext: Boolean
  def next(): A

class IntIterator(to: Int) extends Iterator[Int]:
  private var current = 0
  override def hasNext: Boolean = current < to
  override def next(): Int =
    if hasNext then
      val t = current
      current += 1
      t
    else
      0
end IntIterator

val iterator = new IntIterator(10)
iterator.next()  // returns 0
iterator.next()  // returns 1

這個 IntIterator 類別將參數 to 作為上限。它 extends Iterator[Int],這表示 next 方法必須傳回 Int。

子類型化

如果需要某個特質,可以使用該特質的子類型。

import scala.collection.mutable.ArrayBuffer

trait Pet {
  val name: String
}

class Cat(val name: String) extends Pet
class Dog(val name: String) extends Pet

val dog = new Dog("Harry")
val cat = new Cat("Sally")

val animals = ArrayBuffer.empty[Pet]
animals.append(dog)
animals.append(cat)
animals.foreach(pet => println(pet.name))  // Prints Harry Sally
import scala.collection.mutable.ArrayBuffer

trait Pet:
  val name: String

class Cat(val name: String) extends Pet
class Dog(val name: String) extends Pet

val dog = Dog("Harry")
val cat = Cat("Sally")

val animals = ArrayBuffer.empty[Pet]
animals.append(dog)
animals.append(cat)
animals.foreach(pet => println(pet.name))  // Prints Harry Sally

trait Pet 有一個抽象欄位 name,由 Cat 和 Dog 在其建構函式中實作。在最後一行,我們呼叫 pet.name,這必須在 trait Pet 的任何子類型中實作。

更多資源

此頁面的貢獻者