简介
里氏替换原则(LSP)核心思想:
- 子类型必须能够替换掉它们的基类型。换句话说,程序中的对象应该可以在不改变程序正确性的前提下被它的子类的对象所替换。
详细说明: - 子类应当可以完全替换基类,而不会改变程序的正确性。
- 子类可以扩展基类的功能,但不应该改变基类的功能。
- 子类应当遵守基类的行为约定。
优缺点
优点:
- 增强代码的可重用性:遵循LSP的代码更容易被重用和扩展。
- 提高系统的健壮性:可以降低由于使用继承而导致的系统不稳定的风险。
- 改善代码的可维护性:使得系统更容易理解和修改。
缺点:
- 可能导致类的层次结构变得复杂。
- 在某些情况下,可能会牺牲一些性能来换取更好的设计。
代码demo
#include <iostream>
#include <vector>
class Bird {
public:
virtual void makeSound() = 0;
virtual ~Bird() = default;
};
class FlyingBird : public Bird {
public:
virtual void fly() {
std::cout << "The bird is flying." << std::endl;
}
};
class Sparrow : public FlyingBird {
public:
void makeSound() override {
std::cout << "Chirp chirp!" << std::endl;
}
};
class Eagle : public FlyingBird {
public:
void makeSound() override {
std::cout << "Screech!" << std::endl;
}
};
class Penguin : public Bird {
public:
void makeSound() override {
std::cout << "Honk honk!" << std::endl;
}
void swim() {
std::cout << "The penguin is swimming." << std::endl;
}
};
void letBirdMakeSound(Bird& bird) {
bird.makeSound();
}
void letBirdFly(FlyingBird& bird) {
bird.fly();
}
int main() {
Sparrow sparrow;
Eagle eagle;
Penguin penguin;
std::vector<Bird*> birds = {&sparrow, &eagle, &penguin};
for (Bird* bird : birds) {
letBirdMakeSound(*bird);
}
std::vector<FlyingBird*> flyingBirds = {&sparrow, &eagle};
for (FlyingBird* bird : flyingBirds) {
letBirdFly(*bird);
}
return 0;
}
- 所有的子类都可以替换它们的基类(Bird)。
- FlyingBird 的子类可以在任何使用 FlyingBird 的地方被使用。
- 我们没有在 Penguin 类中强行实现 fly() 方法,而是创建了一个单独的 FlyingBird 类。