Source From Here
抽象成員
在這邊所謂的 抽象成員,指的是在抽象類別或特徵(Trait)所定義的成員,像是使用 val、var 宣告的資料成員(Field),或是使用 def 所宣告的方法。在抽象類別或特徵(Trait)中定義抽象資料成員,不需要提供初始值,定義抽象方法時,不需要提供實作,繼承的子類別必須提供資料成員初始值或者是方法實作。例如:
抽象成員
在這邊所謂的 抽象成員,指的是在抽象類別或特徵(Trait)所定義的成員,像是使用 val、var 宣告的資料成員(Field),或是使用 def 所宣告的方法。在抽象類別或特徵(Trait)中定義抽象資料成員,不需要提供初始值,定義抽象方法時,不需要提供實作,繼承的子類別必須提供資料成員初始值或者是方法實作。例如:
- trait Something {
- val some: String
- def doSome: String
- }
- class Other extends Something {
- val some = "some"
- def doSome = "do...some"
- }
- trait Something {
- val some: String
- def data: String
- }
- class Other extends Something {
- val some = "some"
- val data = "data"
- }
如果是個 var 抽象成員,在子類別中可以這麼定義其初始值:
- trait Something {
- var some: String
- }
- class Other extends Something {
- var some = "some"
- }
- trait Something {
- def some: String
- def some_=(s: String)
- }
所以,對於一個抽象 var 成員,你可以如下實作沒有問題,編譯器並不會抱怨:
- trait Something {
- var some: String
- }
- class Other extends Something {
- private[this] var s = "some"
- def some: String = "XD"
- def some_=(s: String) { this.s = s }
- }
如果你想實作某個抽象類別,但不想要定義出類別名稱,也就是你想要以 匿名類別(Anonymous class)的方式對抽象類別實作並實例化,則以下是個例子:
- abstract class Something(val s: String) {
- def doSome: String
- }
- val something = new Something("XD") { def doSome = s + "...done" }
- println(something.doSome) // XD...done
以下則是個使用特徵的例子:
- trait Something {
- def doSome: String
- }
- val something = new Something { def doSome = "XD...done" }
- println(something.doSome)
抽象類別可以宣告主要建構式,但特徵不行,這決定了你是否透過主要建構式傳入參數來初始化抽象成員。就前兩個例子而言,結果沒什麼不同,但如果是以下的例子,需注意一下執行的順序:
- abstract class Something(val s: String) {
- println("主要建構式")
- def doSome: String
- }
- def doIt = {
- println("函式執行")
- "XD"
- }
- val something = new Something(doIt) { def doSome = s + "...done" }
- println(something.doSome)
在使用 匿名類別 實作 Something 並建立實例時,要傳入建構式參數,值是由 doIt 函式決定,所以 doIt 函式會先執行,接著是 Something 主要建構式,也就是會先顯示"函式執行",接著再顯示 "主要建構式",最後呼叫 something.doSome 時,顯示 "XD...done"。
如果是以下的例子:
如果是以下的例子:
- trait Something {
- println("主要建構式")
- def doSome: String
- }
- def doIt = {
- println("函式執行")
- "XD"
- }
- val something = new Something { def doSome = doIt + "...done" }
- println(something.doSome)
這邊一樣以匿名類別實作 Something 並建構實例,此時會先執行 Something 主要建構式,也就是先顯示 "主要建構式",但在執行 something.doSome 時,才會執行 doIt 函式取得其結果,也就是顯示 "函式執行",接著與 "...done" 字串串接後傳回,也就是最後顯示 "XD...done"。或許你會覺得,放在 doSome 方法中的 doIt 很顯然地,必須呼叫 doSome 方法才會被執行不是嘛?是的!但如果是以下這個例子,就不是那麼明顯了:
- trait Something {
- println("主要建構式")
- def doSome: String
- }
- def doIt = {
- println("函式執行")
- "XD"
- }
- val something = new Something { val doSome = doIt + "...done" }
- println(something.doSome)
這邊一樣以 匿名類別 實作 Something 並建構實例,此時會先執行 Something 主要建構式,也就是先顯示 "主要建構式",接著執行匿名類別主要建構式,此時呼叫 doIt 以取得結果,所以會顯示 "函式執行",再來是 something.doSome 呼叫,所以最後是顯示 "XD...done"。
沒有留言:
張貼留言