不是抽象類別的基類不是好基類

來源:互聯網
上載者:User

開宗明義:不是抽象類別的基類不是好基類。為什麼這麼說?

 

基類和衍生類別的關係有如下幾種:


基類可以是具體類、虛類和抽象類別三種,對衍生類別沒有要求。其中具體類是沒有虛函數的類,其所有方法都提供了具體實現;衍生類別方法如果和基類方法同名,則衍生類別方法隱藏(overwrite)了基類方法。虛類是包含虛函數的類,所有方法都提供具體實現;衍生類別如果要提供不同於基類虛方法的實現,則在衍生類別中提供同名方法,該方法將覆蓋(override)基類虛方法。抽象類別是包含抽象方法(或稱為純虛方法)的類,抽象方法不提供具體實現,抽象類別只用於表示概念,不能直接構造抽象類別的對象,抽象類別的極端化就是“介面”。

 

首先,從語義上理解。

衍生類別和基類一定要滿足“is-a”關係,即衍生類別和基類有類屬關係,或者說衍生類別是基類的一種具體化。基類表示某種概念,衍生類別表示該概念下的某類具體事物。


讓一個類繼承自另一個具體類明顯是不合理的,即使他們表示的概念很相近,或者他們的關係很緊密,這相當於說事物A是一種事物B。比如讓直升機繼承自固定翼飛機,明顯,直升機並不是一種固定翼飛機,雖然它們有“fly”這個方法。正確的抽象方式是,提取出飛機這個概念作為基類,然後讓直升機和固定翼飛機都從基類飛機繼承。


讓衍生類別從虛類繼承也是不合理的,卻是常見的錯誤思路,在很多OOP入門教材上用濫了的例子。即,虛基類提供預設實現,如果衍生類別的行為和基類不同,則在衍生類別中覆蓋基類虛方法。

其實,由於虛基類提供了所有方法的實現,說明虛基類並不虛,是一個表示具體事物的具體類。在語義上的問題,同樣可以用前述例子來說明。

 

其次,從程式設計角度理解。

讓衍生類別繼承自具體基類的動機在於,衍生類別的某些行為和具體基類相同,衍生類別想要重用基類的這部分代碼。而在另一些行為上衍生類別和基類又有差別,於是在衍生類別實現了和基類同名的方法(為了保持介面一致,所以同名)來定義自己的行為。從虛基類獲得衍生類別的動機同上,同時還享受了多態性的好處。

但是上述方式的問題在於:

1、沒有遵循“依賴倒置”原則,應對變化的能力不足。OO設計裡的一條重要原則就是:針對抽象編程,而不是針對具體對象編程,這條原則也叫做“依賴倒置”原則。基類充當了類繼承樹和外部世界之間的介面角色,使用者通過基類介面使用這個類繼承樹。如果用具體基類或虛基類作為介面,當類繼承樹內部發生變化時,就會影響到使用者代碼,可能要求使用者代碼修改或者重新編譯。

2、可能造成代碼重複。假設衍生類別重新實現了基類的方法foo,其他方法都相同。如果衍生類別::foo的實現和基類::foo完全不同,正說明了衍生類別和基類並沒有類屬關係,而是在概念上和基類處於同一層次的另一事物。如果衍生類別::foo的實現和基類::foo相似,只是細節不同,那麼它們中必然存在大量實現相同功能的代碼,這違反了同一份資料或代碼只出現一次的要求,正是bug的主要來源之一;解決方案是提取出抽象類別,運用模板方法(template
method)模式。

還是以飛機的例子來說明。


方案一,直升機和固定翼飛機的飛行方式完全不同,所以直升機::fly需要完全重新改寫固定翼飛機::fly,在概念和實現上都是urgly的。於是有方案二:


方案二,提取抽象類別飛機,定義抽象方法fly,然後在其衍生類別固定翼飛機和直升機中分別實現fly方法。

現在變化來了,要將陸基戰鬥機和艦載戰鬥機加入這個體繫結構中。我們知道,陸基和艦載飛機在在空中的飛行方式是一樣的,不同的是艦載機在起飛和降落時有特殊要求。這意味著,陸基戰鬥機和艦載戰鬥機可以重用固定翼飛機::fly方法的大部分代碼。


方案三,運用模板方法模式,將飛機起飛方式作為抽象方法,將固定翼飛機提取為抽象類別,在陸基戰鬥機和艦載戰鬥機中分別實現起飛方法。飛機類和固定翼飛機類都成為了抽象類別。

那麼,如果按照從具體基類或虛基類發展類繼承體系的思路,最後將會得到什麼樣的設計呢?很可能是下面這樣的。


固定翼飛機::fly實現陸基飛行方法;艦載戰鬥機::fly實現copy固定翼飛機::fly的大部分代碼,然後添加艦載起飛方式;直升機::fly完全重寫fly方法。它還是可以工作的,不過概念不清,可擴充性差。

 

 

結論:

1、如果以具體類或者虛類作為基類,說明抽象得還不夠,概念沒理清,物件模型需要進一步分析,提取出抽象基類。

2、如果基類和衍生類別的同名方法實現完全不同,則將此同名方法作為抽象類別的抽象方法;如果上述同名方法實現部分相似,則運用模板方法模式設計。

 

最終得到的類繼承樹中,所有的葉子節點都是且僅是具體類,根節點和所有中間節點都是且僅是抽象類別。如:

 

不是抽象類別的基類不是好基類!


本文來自liudows部落格。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.