2012年4月4日 星期三

[筆記] 全文轉錄 - 少用繼承

 作者  ie945167 (龍蝦)                                      站內  Lobster
 標題  [筆記] 全文轉錄 - 少用繼承
 時間  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 發表

沒有留言:

張貼留言