![5294db75dc1342349205acafb2c5305a.png](https://img-blog.csdnimg.cn/img_convert/5294db75dc1342349205acafb2c5305a.png)
里氏替换原则
上一篇文章我们学习了SOLID中的开闭原则(O),如果还不了解开闭原则的小伙伴可以先去看了我的这篇文章再回来噢想做软件开发得先搞懂软件的设计原则—SOLID原则之开闭原则
今天我们的主题是SOLID中的L,也就是里氏替换原则;
里氏替换原则(以Barbara Liskov的名字命名)规定,如果一个接口接受一个父类型的对象,那么它应该同样接受一个子类型的对象,而不会破坏任何东西。让我们来看看LSP(Liskov Substitution Principle)被打破的情况。
以一个矩形为例:
public class Rectangle { public int Width { get; set; } public int Height { get; set; } public Rectangle() { } public Rectangle(int width, int height) { Width = width; Height = height; } public override string ToString() { return $"{nameof(Width)}:{Width},{nameof(Height)}:{Height}"; } }
正方形继承矩形并重写父类属性:
public class Square : Rectangle { public new int Width { set { base.Width = base.Height = value; } } public new int Height { set { base.Width = base.Height = value; } } }
一个静态方法,接收一个Rectangle参数,求面积:
public static int Area(Rectangle r) => r.Width * r.Height;
使用示例:
Rectangle rc = new Rectangle(2, 3);Console.WriteLine($"{rc} has area {Area(rc)}");Square sq = new Square();sq.Width = 3;Console.WriteLine($"{sq} has area {Area(sq)}");
这样看起来好像没问题:
![cbef8cf7e5852898b03d9bfb65075ef9.png](https://img-blog.csdnimg.cn/img_convert/cbef8cf7e5852898b03d9bfb65075ef9.png)
运行结果
但是一旦把子类替换成父类(把Square替换成Rectangle),那么问题就来了:
Rectangle rc = new Rectangle(2, 3);Console.WriteLine($"{rc} has area {Area(rc)}");Rectangle sq = new Square();sq.Width = 3;Console.WriteLine($"{sq} has area {Area(sq)}");
输出结果就有问题了:
![bc303ee17e8600d61291045406976802.png](https://img-blog.csdnimg.cn/img_convert/bc303ee17e8600d61291045406976802.png)
运行结果
这就不符合里氏替换原则了,因为Square覆盖了父类的方法,当用Square实例化一个Rectangle类的时候实际上调用的还是父类的方法;
所以这里改一下代码,在父类中把属性改为virtual,在子类中override父类的属性,那么在调用的时候就会调用子类的属性了:
public class Rectangle { public virtual int Width { get; set; } public virtual int Height { get; set; } public Rectangle() { } public Rectangle(int width, int height) { Width = width; Height = height; } public override string ToString() { return $"{nameof(Width)}:{Width},{nameof(Height)}:{Height}"; } } public class Square : Rectangle { public override int Width { set { base.Width = base.Height = value; } } public override int Height { set { base.Width = base.Height = value; } } }
再次运行代码就会得到正确的结果啦。
今天的学习就到这了,下次我们学习SOLID原则中的接口隔离原则(I)。