设计模式之里氏替换原则
里氏替换原则(LSP: Liskov Substitution Principle)
定义:####:
- 子类可以扩展父类的功能,但不能改变父类的原有功能
- 子类可以继承父类,但是不能覆盖父类的非抽象方法
- 程序中将任意一个基类对象替换成子类对象,程序不会产生任何异常。反过来则不成立。
- 每一个使用基类的地方,都可以透明的使用子类对象
- 里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
- OOP多态的使用
public class People
{
public void SayHIStandard()
{
Console.WriteLine("普通话:你好");
}
}
public class HubeiPeople : People
{
public new void SayHIStandard() //破坏父类的标准,覆盖了父类的方法
{
Console.WriteLine("湖北话:你好");
}
}
public class SichuanPeople : People
{
public new void SayHIStandard() //破坏父类的标准,覆盖了父类的方法
{
Console.WriteLine("四川话:你好");
}
}
People people = new People();
people.SayHIStandard();
HubeiPeople hbPeople = new HubeiPeople();
people.SayHIStandard(); //并非父类定义的标准,覆盖了父类的方法
SichuanPeople scPeople = new SichuanPeople();
people.SayHIStandard(); //并非父类定义的标准,覆盖了父类的方法
上述代码,明显违反了里氏替换原则,子类覆盖了父类的非抽象方法,那么当程序所有使用基类的地方,换上子类的实例,也将改变原程序的结果。根据里氏替换原则,我们更新代码如下:
public abstract class People
{
public void SayHIStandard()
{
Console.WriteLine("普通话:你好");
}
public abstract void SayHICustom();
}
public class HubeiPeople : People
{
public override void SayHICustom()
{
Console.WriteLine("湖北话:你好");
}
}
public class SichuanPeople : People
{
public override void SayHICustom()
{
Console.WriteLine("四川话:你好");
}
}
People hbPeople = new HubeiPeople();
hbPeople.SayHIStandard();
hbPeople.SayHICustom();
People scPeople = new SichuanPeople();
scPeople.SayHIStandard();
scPeople.SayHICustom();
按照里氏替换原则更新代码过后,不仅可以继续使用基类的原有标准SayHIStandard()方法,还可以调用子类扩展的SayHICustom()方法
使用总结:
- 尽量声明的时候用父类,而不是具体的子类
- 子类不要覆盖父类的方法,如果有需要,父类的方法应该定义为abstract/virtual,子类override.
网友评论