2011年1月3日 星期一

OOP 中,「是一個...」或「屬於...」

作者: littleshan (我要加入劍道社!) 看板: C_and_CPP
標題: Re: [問題] OOP繼承
時間: Fri May  8 11:33:58 2009

※ 引述《phdch (我們都活在這個城市裡面)》之銘言:
: 下面程式碼
: class Apple:public Fruit
: 中的修飾詞public
: 我知道是存取權限多少的關係
: class中的public成員,private成員,我理解
: 但public的類別(Fruit)要怎麼解釋與子類別(Apple)的關係最好呢???
: 感謝

簡單的說法是「Apple 是一種 Fruit」 (Apple is-a Fruit)
但其實這樣的說法可能會引人誤解,
因為在 OOP 中,「is-a」和一般人對「是一個...」或「屬於...」的認知有一點不同

在 OOP 中,Apple is-a Fruit 意指所有對父類別 (Fruit) 的操作,都可以
運用在子類別 (Apple) 身上。比如說 Fruit 提供了 taste() 這個成員函式,
可以傳回該水果嘗起來的味道,那麼 Apple 也有義務提供 taste() 這個函
式,顯示出蘋果的味道如何。

    class Fruit {
        public:
            virtual string taste() = 0;
    };

    class Apple : public Fruit {
        public:
            virtual string taste()
            {
                return "Apple is sweat.";
            }
    };

這樣的好處是,對於不同種類的水果,我們都可以用相同的操作去顯示它的味道:

    class Lemon : public Fruit {
        public:
            virtual string taste()
            {
                return "Lemon is sour."; // 檸檬很酸
            }
    };

    class ArtificialFruit : public Fruit { // 某種人造水果
        public:
            virtual string taste()
            {
                string result;
                ... // 進行某些複雜的運算來得到它的味道
                return result;
            }
    };

    void print_taste(Fruit& fruit)
    {
        // 我不知道 fruit 是什麼水果
        // 但我知道,只要是 Fruit,就可以用 taste() 取得它的味道
        cout << fruit.taste() << endl;
    }

    int main()
    {
        Apple apple;
        Lemon lemon;
        ArtificialFruit unknow;

        // apple is-a Fruit
        // Fruit 提供 taste() 來取得水果的味道
        // 所以 apple 也可以用 taste() 來取得味道
        print_taste(apple);

        print_taste(lemon);  // 同上,印出檸檬的味道
        print_taste(unknow); // 同上,印出某種未知的味道

        return 0;
    }

不管你發明怎樣的水果,只要這種水果提供 taste() 界面,那你不需要修改
既有的 print_taste 程式碼,就可以印出該水果的味道。這正是 OOP 中最
基本的概念。

至於 private inheritance,在概念上和 public inheritance 有極大的不同,
它並不會形成 is-a 的關係,而比較類似 has-a。如果你對這些議題有興趣,
建議你可以看看以下的參考資料:

 *   Effective C++ 條款 35:確定你的 public inheritance 模塑出 is-a 的關係
                   條款 36:區分介面繼承及實作繼承
                   條款 42:明智地運用 private inheritance

 * Exceptional C++ 條款 22:class 設計的常見錯誤

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 219.87.151.2
推 VictorTom:推:)  小弟今天負責來推文的就對了XD                    05/08 12:38
推 Peruheru:這篇文章真有趣                                         05/08 12:38

沒有留言:

張貼留言

您好.本資料庫並非第一手資料.如果你有對文章作者的詢問,意見與需求,請自行找尋文章作者並提供意見,謝謝.