標題 [筆記] 全文轉錄 - 少用繼承
時間 2012/04/04 Wed 17:46:41
───────────────────────────────────────
http://imandrewliao.blogspot.com/2009/01/blog-post_07.html
物件導向程式設計中,為了提升程式碼的再利用性,提供了繼承這樣的架構給我們使用,
只要看不順眼的類別,就可以用繼承改寫舊功能,達到擴展的目的,範例如下:
class AI
{
private:
virtual void FSM(); // AI類別實做FSM
};
class Monster : public AI
{
private:
virtual void FSM(); // Monster類別改寫原來的函式
};
但就"程式碼再利用的"目的而言,事實上,我們常用的方法還有一種,
"組成",利用物件彼此間的協力,完成特定工作,
譬如,老闆要求去做一件A、B君都只會做部分功能的工作,
依照繼承的觀念,是否要生成第三個類別C,繼承A、B的能力,
然後改寫部分關聯而增加的程式碼?
然而我們是不是可以換個方向思考,
我可以設計個類別C,工作交代C,C會先請A君做完他會做的,
然後B繼續接手,一樣可以完成工作,
與繼承兩者,事實上複雜度一樣,都需要3個類別,
但是程式維護的小心程度卻是不可相提並論,程式如下
class AI
{
public:
void FSM();
};
class TimeControl
{
public:
void DoSomething();
};
用繼承:
class Npc:public AI, public TimeControl
{
void DoSomething(); // 這裡遭遇第一個難關
// 多重繼承,要小心AB的成員變數、成員函式設計關係
};
用組成:
class Npc
{
private:
AI ai;
TimeControl tc;
public:
void DoSomething(); // 我可以在這裡,靈活運用ai, tc物件的函式
// 達成老闆目標
};
你可以看見,往後ABC三個類別的修改,相依性是否會降低很多很多,
說白話,只要AB類別確定功能正常,發生BUG一定就是C,
A類別新增怎樣的功能,不會影響C或B的運作,同理C增減怎樣的函式,AB都不會影響,
而使用繼承呢? 就算你確定ABC三類別功能都正確,卻有可能因為繼承的關係,
造成邏輯錯誤,像是C發生BUG的原因,是因為C修改了一個變數值,
然後是A或B非常重要的變數,不允許由外部變更的
(這裡有個小伏筆,避免修改到別人家的變數,變數請用private封裝...)。
加上有許多程式濫用繼承,一個遊戲專案裡頭隨便都成千上百個類別,
加上彼此繼承的關係,專案像是N坨大肉粽樹,盤根錯節,
某Z類別有BUG,原因卻是在千里之外八竿子打不到關係的A類別造成,
改了A,卻連鎖反應要把某個肉粽樹的函式都要改過,想到就累人啊,
所以,有得選的情形下,請少用繼承多用組成。
再舉個生活上的例子,老闆要設計個簡報在客戶面前推銷商品,為了達到目標,
他需要繼承文書小姐的能力+產品部門對商品規格特色了解的能力+簡報能力+....,
或者,
他可以把公司內文書小姐、產品部經理、行銷推廣部經理叫來,說出需求,
接下來大家就自動會把事情搞定,而老闆則可專心挑毛病去,
愛用繼承的,通常工作累得要死,
愛用組成的,通常是老闆,你選哪個?
--
▅◣ Origin: 謠 言 報 bbs.csie.fju.edu.tw
▋◤ Author: ie945167 從 219-85-0-189-adsl-nei3.dynamic.so-net.net.tw 發表
沒有留言:
張貼留言