#里氏替换原则
-
继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
-
总的来说继承机制是利大于弊的。但为了突出其“利”的一面,减少其“弊”的一面,故引入了里氏替换原则(Liskov Substitution Principle,LSP)。它有以下两种定义:
1.If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substisuted for o2 then S is a subtype of T.
2.Functions that use pointers or references to base classes must be able to use objects of derived classes without konwing it.
- 通俗的说,即父类出现的地方子类也可以出现,并且将父类用子类替换后,也不会产生任何问题。然而,需要注意的是里氏替换原则反过来使用是不行的,子类出现的地方,父类未必适用。
- 在使用继承时,遵循里氏替换原则,在子类中 尽量不要重写父类的方法.
里氏替换原则为良好的继承定义了一个规范,一句简单的话包含了4层含义。
1、子类必须完全实现父类的方法
在类中调用其它类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计以及违背了LSP原则。
如果子类不能完整的实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。
2、子类可以拥有自己的“个性”
子类可以拥有自己的方法和属性,也可以重写(Override)或重载(Overload)父类的方法。从而拥有自己的“个性”。但这里提起是为了再次说明一个问题——里氏替换原则可以正着用,但不能反过来使用,即子类出现的地方,父类未必可以胜任。
3、覆盖或实现父类方法时输入参数可以被放大
父类的一个方法的形参是一个类型T,子类的相同方法(重载或重写)的形参是S,那么里氏替换原则就要求S必须大于等于T。也就是说,要么S和T是同一类型,要么S是T的父类
。
4、覆盖或实现父类方法时输出结果可以被缩小
父类的一个方法返回值是一个类型T,子类的相同方法(重载或重写)的返回值是S,那么里氏替换原则就要求S必须小于等于T。也就是说,要么S和T是同一类型,要么S是T的子类
。