gpt4 book ai didi

c++ - 具有多重继承层次结构的 Liskov 替换原则

转载 作者:行者123 更新时间:2023-11-28 06:01:10 26 4
gpt4 key购买 nike

我想提出一个面向对象的设计,但很难满足里氏替换原则。这是一个说明性示例:

class Food
{
public:
virtual void printName() {
//......
}
};
class Fruit : public Food
{
};
class Meat : public Food
{
};
class Animal
{
public:
Food *_preferredFood;
virtual void setFoodPreference(Food *food)=0;

};
class Carnivore: public Animal
{
public:
void setFoodPreference(Food *food) {
this->_preferredFood = dynamic_cast<Meat *>(food);
}
};
class Herbivore: public Animal
{
public:
void setFoodPreference(Food *food) {
this->_preferredFood = dynamic_cast<Fruit *>(food);
}
};

我如何执行以下操作:

  1. Animal 的每个子类都应该允许设置食物偏好,而不会破坏 LSP
  2. 每个派生类动物的食物偏好是食物的一个子类

例如,如果有人扩展 Animal 以创建 MarineMammal,则食物偏好可能是 Fish(他们将通过扩展 创建>食物).

最佳答案

Carnivore::setFoodPreference 只接受 MeatHerbivore::setFoodPreference 只接受 Fruit 时,那么它们不遵守同一份契约(Contract)。这意味着它们实际上不是同一种方法。当你调用这个方法时,你必须知道你是在处理食肉动物还是食草动物,以避免传递错误的类型。当您忘记检查它时,您可能会产生一个错误,该错误会在运行时以转换错误的形式出现。

解决方案是将这两种方法分开。

我建议您从公共(public)接口(interface)中删除 setFoodPreference 并添加方法 Carnivore::setMeatPreference(Meat *meat)Herbivore::setFruitPreference( Fruit *fruit) 直接给子类。这样一来,任何设置食物偏好的代码都必须知道它处理的是哪种动物和哪种食物,因此您不能再编写试图设置不兼容食物类型的代码。

在内部,这两种方法都可以从公共(public)基类设置一个protected Food *_preferredFood。或者甚至更好,调用 protected void setPreferredFood(Food *food),它是 private Food* _preferredFood 的 setter 。该变量绝对不应公开以确保正确封装。

关于c++ - 具有多重继承层次结构的 Liskov 替换原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33268558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com