在钻石问题上更倾向于组合而非继承



假设我们有三个类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的三种形式之外(是,我觉得我打破了组合而非继承原则,因为我继承只是为了包含一个变量
是否存在具有相同行为的设计模式?在这种情况下我该如何使用作文?

编辑:

我正在寻找一种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类也会很痛苦。如果你喜欢的话,指针也可以实现这一点。

继承为is-a关系建模。如果Horse继承自Animal,那么Horse就是Animal,因为动物的所有特性也是马的特性。

现在,在您的例子中,说Button就是Clickable有意义吗?是的,因此继承是适用于作业的工具。说Button就是Rectangle有意义吗?好吧,现在我们陷入了浑水。

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

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

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

编辑

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

最新更新