簡體   English   中英

在鑽石問題中更喜歡組合而不是繼承

[英]Preferring composition over inheritance in the diamond problem

假設我們有 3 個類ButtonClickableRectangle
它們都不是抽象的,可以獨立存在。 它們都有一個position成員變量。 Button類從ClickableRectangle繼承時,它們應該共享一個公共position變量。
我的實現:

struct Positionable {
    struct Position {
        int x, y;
    } position;
};
struct Rectangle: virtual public Positionable {
    // ...
};
struct Clickable : virtual public Positionable {
    // ...
};
struct Button : virtual public Positionable, public Rectangle, public Clickable {
    Button() {
        this->position.x = 1;
        assert(Rectangle::position.x == 1);
        assert(Clickable::position.x == 1);
        assert(Positionable::position.x == 1);
    }
} test;

這個問題(除了詞position的 3 種形式)是我覺得我打破了繼承原則的組合,因為我繼承只包含一個變量。
是否有具有相同行為的設計模式? 在這種情況下如何使用組合?

編輯:

我正在尋找一種解決方案,其中Button繼承自ClickableRectangle ,因為它是一種 is-a 關系。 (這可能不是最好的例子,但假設它是真的)
我也不想從Positionable繼承,因為它是一個 has-a 關系。
我想要與我的實現相同的行為,所以:

  • 他們都有一個Position position
  • 當它們相互繼承時,它們共享這個變量
  • 我不使用 setter/getter

基本上我想要像虛擬變量這樣的東西,但是 c++ 還沒有那個功能,所以我正在尋找一個明智的替代品。

我沒有完全看到您的問題,但是您可以使用引用來實現這一點。 您可以執行以下操作:

struct Position{
    int x,y;
};

class Rectangle {
    public:
        Rectangle(Position& p) : pos(p) {}
        ~Rectangle() {}
        Position getPos(){ return pos; }
    protected:
        Position& pos;
};

class Clickable {
    public:
        Clickable(Position& p) : pos(p) {}
        ~Clickable() {}
        Position getPos(){ return pos; }
    protected:
        Position& pos;
};

class Button {
    public:
        Button(int x, int y) : pos({x,y}), a(this->pos), b(this->pos) {}
        ~Button() {}
        Position getPos(){ return pos; }
    protected:
        Position pos;
        Clickable a;
        Rectangle b;
};

不過這很亂。 如果你問我,使用原始RectangleClickable類也很痛苦。 如果您喜歡,指針也可以實現這一點。

繼承模型是一種關系。 如果Horse繼承自Animal ,那么Horse就是Animal ,因為動物擁有的所有屬性也是馬的屬性。

現在,在您的示例中,說Button是可Clickable是否有意義? 是的,所以繼承是這項工作的適用工具。 ButtonRectangle有意義嗎? 好吧,現在我們陷入了泥濘的水域。

如果我們打算通過ButtonRectangle子接口使用它(也許一個簡單的渲染器可以接收矩形派生對象並渲染它們),那么在這里繼承也是合適的。 但是,如果使用繼承是因為它是正確的 OOP 並且這是需要做的事情,那么不。

權衡你需要什么,看看它是否合乎邏輯。 先想想是否應該,然后再考慮是否可以。

PS:我不明白為什么Clickable不是抽象的。 這聽起來像一個界面。 如果它不是接口,那么您嘗試建模的概念可能有一個更好的名稱。

編輯

我突然想到,如果您使用 C++,您可能需要研究private繼承。 這就是你所說的實現繼承 C++ 常見問題解答: https : //isocpp.org/wiki/faq/private-inheritance

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM