如何解决在钻石问题中更喜欢组合而不是继承
假设我们有 3 个类 Button
、Clickable
和 Rectangle
。
它们都不是抽象的,可以独立存在。它们都有一个 position
成员变量。当 Button
类继承自 Clickable
和 Rectangle
时,它们应该共享一个公共的 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
继承自 Clickable
和 Rectangle
,因为它是一种 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;
};
虽然这很乱。如果你问我,使用原始 Rectangle
和 Clickable
类也很痛苦。如果您愿意,指针也可以实现这一点。
继承模型是一种关系。如果 Horse
继承自 Animal
,则 Horse
是 Animal
,因为动物的所有属性也是马的属性。
现在,在您的示例中,说 Button
是 Clickable
是否有意义?是的,所以继承是这项工作的适用工具。说 Button
是 Rectangle
有意义吗?好吧,现在我们陷入了泥泞的水域。
如果我们打算通过 Button
子接口使用 Rectangle
(也许一个简单的渲染器可以接收矩形派生对象并渲染它们),那么继承在这里也是合适的。但是如果使用继承因为它是适当的 OOP 并且这是需要做的事情,那么不。
权衡你需要什么,看看它是否合乎逻辑。先考虑是否应该,然后再考虑是否可以。
PS:我不明白为什么 Clickable
不是抽象的。这听起来像一个界面。如果它不是一个界面,那么您尝试建模的概念可能有一个更好的名称。
编辑
我突然想到,如果您使用 C++,您可能需要研究 private
继承。这就是您所说的实现继承。 C++ 常见问题解答:https://isocpp.org/wiki/faq/private-inheritance
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。