Scala Trait 的基本概念

2018-09-28 18:19 更新

Trait 的基本概念

在 Scala中Trait 為重用代碼的一個(gè)基本單位。一個(gè) Traits 封裝了方法和變量,和 Interface 相比,它的方法可以有實(shí)現(xiàn),這一點(diǎn)有點(diǎn)和抽象類定義類似。但和類繼承不同的是,Scala 中類繼承為單一繼承,也就是說子類只能有一個(gè)父類。當(dāng)一個(gè)類可以和多個(gè) Trait 混合,這些 Trait 定義的成員變量和方法也就變成了該類的成員變量和方法,由此可以看出 Trait 集合了 Interface 和抽象類的優(yōu)點(diǎn),同時(shí)又沒有破壞單一繼承的原則。

下面我們來看看Trait的基本用法:

定義一個(gè) Trait 的方法和定義一個(gè)類的方法非常類似,除了它使用 trait 而非 class 關(guān)鍵字來定義一個(gè) trait。

trait Philosophical{
  def philosophize() {
    println("I consume memeory, therefor I am!")
  }
}

這個(gè) Trait 名為 Philosophical。它沒有聲明基類,因此和類一樣,有個(gè)缺省的基類 AnyRef。它定義了一個(gè)方法,叫做 philosophize。這是個(gè)簡(jiǎn)單的 Trait,僅夠說明 Trait 如何工作。

一但定義好 Trait,它就可以用來和一個(gè)類混合,這可以使用 extends 或 with 來混合一個(gè) trait。例如:

class Frog extends Philosophical{
  override def toString="gree"
}

這里我們使用 extends 為 Frog 添加 Philosophical Trait 屬性,因此 Frog 缺省繼承自 Philosophical 的父類 AnyRef,這樣 Frog 類也具有了 Philosophical 的性質(zhì)(因此 Trait 也可以翻譯成特質(zhì),但后面我們還是繼續(xù)使用 Trait 原文)。

scala> val frog = new Frog
frog: Frog = green
scala> frog.philosophize
I consume memeory, therefor I am!

可以看到 Frog 添加了 Philosophical(哲學(xué)性)也具有了哲學(xué)家的特性,可以說出類似“我思故我在”的話語(yǔ)了。和 Interface 一樣,Trait 也定義一個(gè)類型,比如:

scala> val phil:Philosophical = frog
phil: Philosophical = green
scala> phil.philosophize
I consume memeory, therefor I am!

變量 phil 的類型為 Philosophical。

如果你需要把某個(gè) Trait 添加到一個(gè)有基類的子類中,使用 extends 繼承基類,而可以通過 with 添加 Trait。比如:

class Animal
class Frog extends Animal with Philosophical{
  override def toString="green"
}

還是和 Interface 類似,可以為某個(gè)類添加多個(gè) Trait 屬性,此時(shí)使用多個(gè) with 即可,比如:

class Animal
trait HasLegs 
class Frog extends Animal with Philosophical with HasLegs{
  override def toString="green"
}

目前為止你看到的例子中,類 Frog 都繼承了 Philosophical 的 philosophize 實(shí)現(xiàn)。此外 Frog 也可以重載 philosophize 方法。語(yǔ)法與重載基類中定義的方法一樣。

class Animal
trait HasLegs 
class Frog extends Animal with Philosophical with HasLegs{
  override def toString="green"
  def philosophize() {
    println("It ain't easy being " + toString + "!")
  }
}

因?yàn)?Frog 的這個(gè)新定義仍然混入了特質(zhì) Philosophize,你仍然可以把它當(dāng)作這種類型的變量使用。但是由于 Frog 重載了 Philosophical 的 philosophize 實(shí)現(xiàn),當(dāng)你調(diào)用它的時(shí)候,你會(huì)得到新的回應(yīng):

scala> val phrog:Philosophical = new Frog
phrog: Philosophical = green
scala> phrog.philosophize
It ain't easy being green!

這時(shí)你或許推導(dǎo)出以下結(jié)論:Trait 就像是帶有具體方法的 Java 接口,不過其實(shí)它能做的更多。Trait 可以,比方說,聲明字段和維持狀態(tài)值。實(shí)際上,你可以用 Trait 定義做任何用類定義做的事,并且語(yǔ)法也是一樣的,除了兩點(diǎn)。第一點(diǎn),Trait 不能有任何“類”參數(shù),也就是說,傳遞給類的主構(gòu)造器的參數(shù)。換句話說,盡管你可以定義如下的類:

class Point(x: Int, y: Int)

但下面的 Trait 定義直接報(bào)錯(cuò):

scala> trait NoPoint(x:Int,y:Int)
<console>:1: error: traits or objects may not have parameters
       trait NoPoint(x:Int,y:Int)
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)