在钻石问题中更喜欢组合而不是继承

问题描述

假设我们有 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,因为动物的所有属性也是马的属性。

现在,在您的示例中,说 ButtonClickable 是否有意义?是的,所以继承是这项工作的适用工具。说 ButtonRectangle 有意义吗?好吧,现在我们陷入了泥泞的水域。

如果我们打算通过 Button 子接口使用 Rectangle(也许一个简单的渲染器可以接收矩形派生对象并渲染它们),那么继承在这里也是合适的。但是如果使用继承因为它是适当的 OOP 并且这是需要做的事情,那么不。

权衡你需要什么,看看它是否合乎逻辑。先考虑是否应该,然后再考虑是否可以。

PS:我不明白为什么 Clickable 不是抽象的。这听起来像一个界面。如果它不是一个界面,那么您尝试建模的概念可能有一个更好的名称。

编辑

我突然想到,如果您使用 C++,您可能需要研究 private 继承。这就是您所说的实现继承。 C++ 常见问题解答:https://isocpp.org/wiki/faq/private-inheritance

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...