我有一组课程:
// This is #included from another header file
// I don't want to inherit this, because it ain't my code
class DrawableObject;
class Animal {
DrawableObject obj;
// Does not define run() or swim()
};
class Cat : public Animal {
void run() { /* Calls obj.setPosition() and other stuff */ }
};
class Dog : public Animal {
void run() { /* Calls obj.setPosition() and other stuff */ }
void swim() { /* Calls obj.setPosition() and other stuff */ }
};
class Dolphin : public Animal {
void swim() { /* Calls obj.setPosition() and other stuff */ }
};
在这里,Dog::run()
和Cat::run()
碰巧使用完全相同的代码,Dog::swim()
和Dolphin::swim()
也使用相同的代码。我不想在整个地方复制粘贴代码,而是想重复使用它。明智的解决方案似乎是在基类(Animal
)和具体类(Cat/Dog/Dolphin
)之间添加中间子类:
/-> RunnableAnimal --> Cat
| \
Animal-| |-> Dog
| /
\-> SwimmableAnimal -> Dolphin
问题是:我是否反对“超越继承的构成”规则?如果是这样,这是完全没问题的,还是有办法在实现代码重用的同时坚持CoI?
注意:我不需要或不需要多态 - 当我使用run()
时,我总是使用具体(Cat/Dog/Sloth
)类而不是基础Animal
类来调用它。
更好的继承模式:
/–––––––––– Cat
/ /
/ Runner
/ \
Animal –––––––––––––– Dog
\ /
\ Swimmer
\ \
\–––––––––– Dolphin
您可以避免使用方法引入的菱形图案。
您可以在需要时在动物中聚合Runner
/ Swimmer
实例,而不是继承,让动物的功能只委托给成员。
关于你的模型只是一个小问题:它并没有真正反映现实,实际上,猫,虽然不喜欢水,也是相当不错的游泳运动员......
编辑:由于Runner
和Swimmer
需要访问Animal
的成员:你可以通过curiously recurring template pattern提供这个;在下面添加了一个演示
class Animal
{
protected:
int n = 7;
};
template <typename T>
class Swimmer
{
public:
void swim()
{
std::cout << static_cast<T*>(this)->n << std::endl;
}
};
class Dolphin : public Animal, public Swimmer<Dolphin>
{
friend class Swimmer; // n is protected!
// (alternatively, Swimmer might already be a friend of Animal)
};
int main(int argc, char* argv[])
{
Dolphin d;
d.swim();
return 0;
}