前言 :
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 特徵抽離共同的介面與實作,類別動態地繼承(extends)或具有(with)特徵.
堆疊修飾 (Stackable modification) :
特徵(Trait)可以讓你定義沒有實作的抽象方法,也可以讓你定義有實作的具體方法,事實上,抽象類別可以作的事,特徵幾乎都可以作(特徵也可以定義資料成員以持有狀態),你可能會想,特徵跟抽象類別有何不同?
就語法上來看,除了類別可以繼承或具有多個特徵,但只能繼承一個抽象類別之外,特徵與抽象類別間的不同點,就是特徵不能定義主要建構式的參數,還有就是特徵中定義方法時,super 呼叫是動態綁定的(類別中的 super 是靜態綁定的,也就是你在類別中寫下super.somMethod() 時,你知道所呼叫的是哪個類別的方法). 特 徵中定義方法時,super 呼叫是動態綁定的,也就是當你在特徵的方法中寫下 super.someMethod() 時,你並不知道真正呼叫的是哪個類別的 方法,只有在某個類別具有該特徵時,才能決定super.someMethod() 所呼叫的是哪個類別的方法,也由於這個特性,在類別具有這類特徵時,得以在呼 叫 super.someMethod() 方法前後作些處理,執行所謂堆疊修飾(Stackable modification)的功能. 舉個例子來說,你打算設計一個點餐程式,目前主餐有炸雞、漢堡,你打算讓點了主餐的客入選擇附餐時可以有優惠,如果您使用繼承的方式來達到這個目的,例如 :
- class FriedChicken {
- def content = "不黑心炸雞"
- def price = 49.0
- }
- class SideDishOne extends FriedChicken {
- override def content = super.content + " | 可樂 | 薯條"
- override def price = super.price + 30.0
- }
附餐 (SideDish) 也是一種餐點,所以抽出 Meal 特徵 規範共同的介面 content 與 price,而附餐一與附餐二重新定義了content 與 price,也就是原來特徵定義是抽象方法,現有定義為有實作內容的方法,不過由於其中用到了 super 呼叫,目前並無法知道這個呼叫到底是呼叫哪個方法,因此加上了 abstract 關鍵字. 現在如何搭配附餐呢?為了詳細示範,先中規中矩地寫的話,可以這麼用 :
- class FriedChickenSideDishOne extends FriedChicken with SideDishOne
- val meal = new FriedChickenSideDishOne
- println(meal.content) // 顯示 不黑心炸雞 | 可樂 | 薯條
- println(meal.price) // 顯示 79.0
- val meal1 = new FriedChicken with SideDishOne
- println(meal1.content) // 顯示 不黑心炸雞 | 可樂 | 薯條
- println(meal1.price) // 顯示 79.0
- val meal1 = new FriedChicken with SideDishOne
- val meal2 = new FriedChicken with SideDishTwo
- val meal3 = new FriedChicken with SideDishOne with SideDishTwo
- val meal4 = new FriedChicken with SideDishTwo with SideDishOne
- println(meal1.content) // 不黑心炸雞 | 可樂 | 薯條
- println(meal1.price) // 79.0
- println(meal2.content) // 不黑心炸雞 | 玉米濃湯 | 咖啡
- println(meal2.price) // 99.0
- println(meal3.content) // 不黑心炸雞 | 可樂 | 薯條 | 玉米濃湯 | 咖啡
- println(meal3.price) // 129.0
- println(meal4.content) // 不黑心炸雞 | 玉米濃湯 | 咖啡 | 可樂 | 薯條
- println(meal4.price) // 129.0
Supplement :
* [OO 設計模式] Decorator Pattern : 裝飾模式 - 動態增加類別功能
沒有留言:
張貼留言