什么是里式替换?
其实原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(BarbaraLiskov)提出来的。
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
里式替换原则含义是什么?
里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
·子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
·子类中可以增加自己特有的方法。
·当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
·当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格
为什么用里式替换?
·减少代码出错率
·规范继承时子类的一些书写规则
·保持父类方法不被覆盖
·里氏替换原则增强了程序的健壮性
·里氏代换原则是实现开闭原则的重要方式之一
里式替换注意那些问题?
在使用里氏代换原则时需要注意如下几个问题:
(1)子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。根据里氏代换原则,为了保证系统的扩展性,在程序中通常使用父类来进行定义,如果一个方法只存在子类中,在父类中不提供相应的声明,则无法在以父类定义的对象中使用该方法。
(2) 我们在运用里氏代换原则时,尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。里氏代换原则是开闭原则的具体实现手段之一。
(3)Java语言中,在编译阶段,Java编译器会检查一个程序是否符合里氏代换原则,这是一个与实现无关的、纯语法意义上的检查,但Java编译器的检查是有局限的。
举例说明
遵守保持所有引用基类的地方必须能透明地使用其子类的对象这一原则,
比如“鸟”是基类,这个基类有一个“飞翔”的行为。当“鸵鸟”继承了“鸟”,这就会引起麻烦,覆写基类“飞翔”的行为吧,这样就不再符合里氏替换原则。“鸵鸟”是不能替换它的基类了。再举个例子,“长方形”是基类,“正方形”是一种特殊的长方形,理所应当“正方形”是“长方形”的子类。“长方形”有单独改变长或宽的行为,对于“正方形”来说,就得改写这两个行为以保证长等于宽。这样就违背了里氏替换原则。当长方形调整了长,又调整宽,在算面积的时候。正方形这个子类就会出错。
C#视频代码展示
在Person类中
public ClassPerson
{
publicvoid PersonHello()
{
Console.WriteLine("我是人类");
}
}
在Student类中
public class Student :Person
{
publicvoid StudentHello()
{
Console.WriteLine("我是学生类");
}
}
在main方法中
Person P=new Student();//将学生类(子类)的值赋值给Person(父类)类;使得Person类中包含了Student类的对象;
((Student)p).StudentHello();//由于父类中包含了子类的对象,我们将父类对象强转为子类对象;
但是,这是针对一个对象而言,比较容易判断,但是,如果有多个类,我们不能简单的判断,因此,加一个小的知识点:
1.is关键字表示类型的转换,返回值为bool类型,用法如下
if(pisStudent)
{
//判断赋值
}
2.as关键字也表示类型转换,如果不能发生转换,则返回值为null,用法如下
Student S=pas Studnet;//as作为关键字转换。
里式替换的分享就到这里,请大家多多指教。