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

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

假设我们有 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?