Re: [問題] 一個設計上的問題(virtual function)
如果類別間的關係能用 composition 建立, 而且作得簡潔漂亮, 就別
用 inheritance.
至少有兩個該用 has-a 關係的理由
1. Attributes 型態全為 builtin types
一般書上常舉的例子: Employee,其實應為 EmployeeData,內含身
為一個雇員應有的資料(名字、地址、薪水等),功能上和C語言的
結構相去不了多少。如果你的 Employee 長得就像這樣,那就是該用
has-a建立關係的理由,例如:program manager has employee data
。
2. 除了 setter/getter 以外, 沒有其他名稱中有 "動詞" 的 methods
物件依行為模式, 大抵上可分為 (a) 生物 (b) 無生物兩種. 生物通
常為了服務別人、或者被服務而被創造出來, 像是 提供/取用系統資
源,或者運算資源等;無生物則是無具備前述條件,用來搭建服務的
基本元件。
舉例來說如果你的 Employee 不像 Animal 一樣會有 walk()、run()
等 methods, 那麼Employee 應改稱為 EmployeeData, 如此一來也不
會進而考慮到該不該繼承的問題。
不要為了方便使用而繼承
是責任不是福利
類別可以分為兩個部分:(a) 介面 (b) 屬性。
介面是提供服務的媒介。所以一旦介面和父類別的相同,甚至直接由父類
別繼承而來,可以料想到的是:「使用者會把子類認為是和父類一樣的服
務提供者」。提供與父類別異質的服務,程式碼將會變得怪異無比,使用
者如果為此而增加程式碼來切換使用服務(就如同你的程式碼),父類別的
介面就形同虛設。
雖然可以透過語法直接存取繼承下來的屬性,但是如果你未曾想過去擴充
父類別的服務,使用繼承反而讓兩個類別關係緊密到就像一個,使用者最
後會偏向於 "只" 使用其中一種。
───────────── 我是分隔線 ─────────────
如果想做到 ProgramManager has EmployeeData 而且又透過 method 來
取用這些資料,可以導入一個中間層:
class HasEmployeeData {
EmployeeData data;
public:
string getName() const {
return data.getName();
}
};
class ProgramManager : public HasEmployeeData { };
如果看到這裡還是覺得繼承才是較佳的解法,仍有下面問題需再考慮:
1. 這裡是否有必要先用父類別指標指向該物件,卻要在使用的時候
頻繁轉型?
如果是,那麼 (1) 轉型以及 (2) 對特定子類別物件作存取的程
式碼應該分別抽取出來成為新的函式,去除這部分對子類別的相
依性。
另外對於你所提出來 pure virtual function 的方案,我倒不認為那可
以成為解決方案。
1. 如果為了部分子類別而設立介面(非全體),那麼你就應該是那些
子類別。意思是,這個父類別沒有存在的必要。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.121.197.115
推
12/16 11:40, , 1F
12/16 11:40, 1F
討論串 (同標題文章)