[轉錄]Re: Inheritance (繼承)
※ [本文轉錄自 Programming 看板]
作者: tinlans ( ) 看板: Programming
標題: Re: Inheritance (繼承)
時間: Wed Nov 19 11:00:04 2008
※ 引述《sorryChen (陳揚和)》之銘言:
: 其實我不懂什麼時候才真正應該用繼承..
: 我的用法只是把繼承structuralize我的code.
重構 (refactoring) 上也常單純是把繼承拿來這樣用,
其實也沒有什麼不對,
這個看重構的書就會看到一大堆類似的例子。
: 比如說我要設計一台跑車的class.
: 我就先設計"交通工具"此class..再設計車這個class 繼承交通工具
: 在設計"跑車"繼承"車", 雖然其實所有的class都是我寫的
: 而且目前我只需要跑車.. 這個物件 但因為這個物件有許多
: memeber function 和 variables 我是靠繼承來把code在功能上
: 分的比較清楚..我還使用多重繼承 來讓一個class有多個class的member
: 和function.
你的目的顯然是 reuse 已經撰寫過的 code,
但是 reuse 已經寫過的 code 並不是非繼承不可,
一般 OO 的書會建議你盡量使用合成 (composition) 取代繼承,
也比較提倡以責任委派 (delegation) 取代繼承。
你的狀況是需要把「行為」本身抽離出來 (就是你想 reuse 的 member functions),
建立一個或一組行為家族的繼承體系,
車子本身負擔的責任就不再包含這些被你抽離的行為,
而是將責任委派給行為物件。
譬如代表 A 類行為繼承體系裡的 base class 是 BehaviorA,
程式碼就可以寫成下面這樣:
class Car {
public:
void setBehavior(BehaviorA *behaviorObj) { behaviorObj_ = behaviorObj; }
void doSomething() { behaviorObj_->doSomething(); }
private:
BehaviorA *behaviorObj_;
};
Car::doSomething() 做的事情就很單純是把任務委派給其它物件,
它本身並不會做任何事情,
至於委派給什麼物件有很多做法,
這裡的做法是讓 Car 和 BehaviorA 家族裡的某物件產生「關聯」,
而建立這種關聯性的方式是採用「合成」的方式,
也就是將 BehaviorA 成為 Car 的一個 data member。
在 OO 的術語裡面還會區分聚合 (aggregation) 跟合成,
像是上面的寫法其實應該叫做聚合,
因為 Car 不主掌 BehaviorA 家族物件的生命週期,
近代 C++ 會以 shared_ptr<BehaviorA> 來更明確的表現聚合概念;
如果你想明確的表現合成概念,
其中一種方法就是在 Car 的建構子裡產生 BehaviorA 家族裡的物件,
然後在解構子裡明確的把它 delete 掉。
: 現在被說這樣做很不好, 誤解了inheritance的真意
: 而且能盡量不用繼承最好...我想版友們一定會叫我去看書
也不是不用最好,
只是如果用的是 public 就要遵循 Liskov Substitution Principle,
否則 user 用起來感覺會很不直覺,
比方說你讓正方形繼承矩形看似合理,
但是可以考慮下面的例子:
Rectangle *shape = makeRectangle(); // 任意產生矩形「家族」的物件
int originalHeight = shape->height();
shape->setWidth(10);
assert(shape->height() == originalHeight);
如果正方形也被歸類在矩形家族裡,
那麼上述的 assert 就有可能發生失敗,
這是因為正方形的 setWidth() 做的事情比矩形保證的還多,
造成家族物件行為上的不一致,
這種狀況就是違反 LSP 的其中一個例子。
當然你高興用 private 或 protected 繼承就不會有這個問題,
不過你將來很可能會遇到語言無法提供「動態繼承」的問題,
也就是說物件之間的繼承關係無法在 runtime 切斷和重新建立,
這時也只有合成和委派能達成相同的目的。
LSP 只有在純 OO 程式才有意義,
如果你是要搭 generic programming 之類的 paradigm 那又是另一回事,
在那邊的世界裡違背 LSP 的 public 繼承,
以及 OO 領域很不喜歡的多重繼承會變得隨處可見,
詳情可參考 Modern C++ Design 之類的書籍。
: 我看來看去還是看不懂為什麼不好
: 請原諒我沒看過pattern design但是有沒有大師可以指點一下
書還是要讀,
不然可能很多東西會解釋不完。
--
Ling-hua Tseng (uranus@tinlans.org)
Department of Computer Science, National Tsing-Hua University
Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design
Researching: Software pipelining for VLIW architectures
Homepage: https://www.tinlans.org
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.110.248
推
11/19 16:57,
11/19 16:57
推
11/19 17:31,
11/19 17:31
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 128.125.87.33
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
OOAD 近期熱門文章
PTT數位生活區 即時熱門文章