看板CompBook
標 題Re: 繼承的特性 ??
發信站清華資訊(楓橋驛站) (Sun Apr 16 13:46:01 2000)
轉信站Ptt!bbs.ee.ntu!freebsd.ntu!news.cs.nthu!maple
【Re: 繼承的特性 ??】
侯捷
[email protected]
http://www.jjhou.com
2000.04.16 第一次發表於
清大.楓橋驛站(140.114.87.5).物件導向版(Computer/oop)
本文將於日後整理於 侯捷網站/散文 2000
----------------------------------------------------------------
這裡有一封 BBS/News OOP 版的貼信,引起我的興趣。
原信如下:
-------------------------------------------↓
發信人:
[email protected] (自是溫柔最傷人), 看板: oop
標 題: Re: 繼承的特性 ??
發信站: 元智大學風之塔 (Wed Apr 12 22:01:15 2000)
> >有時繼承的使用,並不遵守現實上的觀念
> >例如:
> >圓是一種橢圓
> >所以繼承時,應該要先寫一個橢圓
> >然後寫一個圓去繼承橢圓
> 這種繼承的方式有可能會違反 Liskov-Substitution Principle
> >所以 橢圓 比 圓 多了一個 data member
> >故我們會寫成
> >橢圓繼承了圓
> 這種方式只是為了繼承圓的 implementation 更是錯誤示範.
> 既然橢圓不是圓就不該繼承圓.
> 在這個情形下最好圓跟橢圓不要互相繼承, 但可以讓兩者
> 有一個共同繼承的 base class.
恩...王蟲兄所言甚是
當初上 侯 Sir 開的課時, 就覺得他舉這個例子怪怪ㄉ
但一直找不到什麼說法來解釋
現在總算一語道破了說
也就是說
繼承樹就會變成
Shape
|
-------------------
| |
Basic Rect Basic Ellipse
| |
-------------- ----------------
| | | |
Rect Square Circle Ellipse
恩恩恩恩.....
可是這樣會不會增加管理的複雜度啊....
---------------------------------------------↑
以下是侯捷的感想:
1. 上課教學所舉例子,有時候視當時使用時機(是否為主講重點,
或只是為了有個繼承體系以做其他講題用途)、講課對象的程度
(是否有一半以上的人從未聽聞所謂 interface inheritance),
而有不同深度的討論。如有同學程度超過老師的預期,宜於上課或
下課繼續追問疑點,可避免讓自己的疑惑一直成為疑惑。
2. 《多型與虛擬》書中亦曾舉過類似上述「以橢圓繼承圓」的例子,
確屬粗糙。然亦不可能於當時剖析 implementation inheritance 和
interface inheritance 的區別。因為當時的情況是希望給一個
「儘量簡化」的繼承體系,以做為「多型」之操練對象。
3. 粗糙就是粗糙,所以比較好的作法是在舉「以橢圓繼承圓」的例子
時,加註少量補充說明與提醒。我將於《多型與虛擬》2/e 中這麼做。
4. inheritance 是個複雜的題目,涵蓋 public/protected/private
base classes,virtual/nonvirtual base classes;virtual/nonvirtual
member functions。欲釐清所有這些觀念,以網路上的簡短討論做為
學習之道並非智舉。最佳辦法就是找一本好書。
5. 推薦一本好書:Effective C++ 2/e,其中有一章專論
「繼承機制與物件導向設計(Inheritance and Object-Oriented Design)。
內容包括:
---------------------------------------------↓
條款35:確定你的 public inheritance 模塑出 "isa" 的關係
Item 35: Make sure public inheritance models "isa."
條款36:區分「介面繼承(interface inheritance)」和
「實作繼承(implementation inheritance)」
Item 36: Differentiate between inheritance of interface and
inheritance of implementation.
條款37:絕對不要重新定義一個繼承而來的非虛擬函式
Item 37: Never redefine an inherited nonvirtual function.
條款38:絕對不要重新定義一個繼承而來的預設參數值
Item 38: Never redefine an inherited default parameter value.
條款39:避免在繼承體系中做 cast down(向下轉型)的動作
Item 39: Avoid casts down the inheritance hierarchy.
條款40:透過 layering(分層技術)來模塑 has-a 或
is-implemented-in-terms-of 的關係
Item 40: Model "has-a" or "is-implemented-in-terms-of"
through layering.
條款41:區分 inheritance 和 templates
Item 41: Differentiate between inheritance and templates.
條款42:明智地運用 private inheritance(私有繼承)
Item 42: Use private inheritance judiciously.
條款43:明智地運用多重繼承(multiple inheritance,MI)
Item 43: Use multiple inheritance judiciously.
條款44:說出你的意思並瞭解你所說的每一句話
Item 44: Say what you mean; understand what you're saying.
---------------------------------------------↑
6. 在「正方形和矩形」(或是橢圓形和圓形)的繼承關係上,
Effective C++ 2/e item35 有這樣的敘述(摘錄):
---------------------------------------------↓
p158~p160 :
或許你會說,你對於鳥類實在缺乏直覺,但是你的幾何學學得不錯。
喔,是嗎?我想說的是,正方形和矩形之間可能有多麼複雜?
好,請你回答這個問題:class Square 應該以 public 的方式繼承
class Rectangle 嗎?
圖
『咄!』你說,『當然應該如此!每一個人都知道正方形是一種矩形,
反之則不一定』。這是真理,至少高中數學課本是這麼教的。但是我
不認為你現在還是高中學生。
考慮這份碼:
....
現在再考慮這份碼,其中使用 public inheritance,允許正方形
被視為一種矩形:
....
歡迎來到 public inheritance 的奇異世界。你在其他領域(包括數學)
學習而得的直覺,在這裡恐怕無法如預期般地有所表現。本例的根本困難
是,某些事情可施行於矩形身上(例如寬度可單獨被修改),卻不可施行
於正方形身上(其寬度總是應該和高度一樣)。但是 public inheritance
主張,每一件事情只要能夠施行於 base class objects 身上 —
每件事情唷! — 就一定可以施行於 derived class objects 身上。
在正方形和矩形的例子中(另一個類似的例子是 sets 和 lists,見條款40),
那樣的主張無法保持,所以以 public inheritance 來模塑它們之間的
關係是錯誤的。編譯器會讓你通過,但是一如我們所見,這並不保證程式
的行為適當(或正確)。每個程式員都必須學得一個教訓:程式碼通過
編譯,並不表示就可以正確運作。
現在,不要因為你發展經年的軟體直覺在與物件導向觀念
打交道的過程中失去效用,便心慌意亂起來。那些知識
還是有價值的,但現在你已經為你的軍械庫加上 inheritance(繼承)
這支大砲,你也必須為你的直覺添加新的洞察力,以便引導你適當地運用
inheritance 這支神兵利器。當有一天有人展示一個數頁長的函式給你看,
你終將回憶起「令 Penguin 繼承 Bird,或是令 Square 繼承 Rectangle」
的概念和趣味;這種繼承方式有可能接近事實真象,但也有可能不是。
是的,當然,「是一種(isa)」並不是唯一存在於 classes
之間的關係。另兩個常見關係是「有一個(has-a)」和「根據
某物實作出(is-implemented-in-terms-of)」。這些關係將在
條款40和42討論。將上述這些重要的相互關係中的任何一個誤塑
為 isa 而造成的錯誤設計,在 C++ 中實不罕見,所以你應該
確定你確實瞭解這些「classes 相互關係」間的差異,並且知道
在 C++ 中如何塑造它們。
---------------------------------------------↑
-- the end
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: [email protected]