特質用於在類別之間共用介面和欄位。它們類似於 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
和方法 hasNext
和 next
的實作。
使用特質
使用 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
的任何子類型中實作。
更多資源
- 在 Scala Book 中深入了解特質
- 使用特質來定義 列舉