C# 设计原则-里氏替换原则

  里氏替换原则,全称Liskov Substitution Principle,英文缩写LSP。

  一个程序中如果使用的是一个父类,那么该程序一定适用于其子类,而且程序察觉不出父类和子类对象的区别。也就是说在程序中,把父类替换成它的子类,程序的行为没有任何变化。

  关于里氏替换原则的反例有不少,举个例子,企鹅不会飞。

  Birds鸟类、Sparrow麻雀类,所有的鸟类都有飞行速度。

public abstract class Birds
{
    //所有鸟类都应该具有飞行速度
    public abstract double FlySpeed();
}

public class Sparrow : Birds
{
    public override double FlySpeed()
    {
        return 12;
    }
}

  此时添加一个Penguin企鹅类,因为企鹅也是鸟类,所以继承Birds鸟类。

public class Penguin : Birds
{
    public override double FlySpeed()
    {
        return 0;
    }
}

  但因为企鹅不会飞,所以飞行速度设为0,这也算是实现了FlySpeed的方法,运行结果也没问题。但如果现在有一个方法Fly用来计算一只鸟飞行300米所需要的时间。

public static double Fly(Birds bird)
{
    return 300 / bird.FlySpeed();
}

  当把企鹅Penguin放进去,会出现报错,因为300/0是不合理的,这就不满足里氏替换原则。不满足该原则的原因还是因为Penguin企鹅类没有完全继承Birds鸟类,因为企鹅不能飞,实现不了FlySpeed方法。所以要解决这个问题有两种方案。

  第一种是直接在Fly方法中进行判断。

public static double Fly(Birds bird)
{
    //如果传入的类型为企鹅,默认返回0
    if (bird.GetType().Equals(typeof(Penguin)))
    {
        return 0;
    }
    else
    {
        return 300 / bird.FlySpeed();
    }
}

  可这样就会违反开闭原则,以后如果需要添加新功能,得不断修改。

  第二种就是Penguin企鹅类不要继承Birds鸟类,实际上,这里Penguin企鹅就是强行继承Birds鸟类,虽然现实中企鹅也是鸟,但在代码中却不行。

  总结一下里氏替换原则的特点,就是子类可以拓展父类的功能,但是不能改变父类原有的功能。子类可以重写父类的抽象方法,但不能覆盖父类的非抽象方法。子类可以增加自己独有的方法。

  

原文地址:https://www.cnblogs.com/shadoll/p/14201608.html