LSP(Liskov Substitution Principle)程序员
定义:子类型必须可以替换掉它们的基类型。spa
若对每一个类型S的对象o1,都存在一个类型T的对象o2。使得在全部针对T编写的程序P中,用o1替换o2后,程序P的功能不变,则说明S是T的子类型!code
一个违反该原则的例子对象
长方形:blog
public class Rectangle { private double _width; private double _height; public void SetWidth(double w) { _width = w; } public void SetHeight(double w) { _height = w; } public double GetWidth() { return _width; } public double GetHeight() { return _height; } }
正方形:继承
public class Square extends Rectangle{ public void SetWidth(double w) { super.SetWidth(w); super.SetHeight(w); } public void SetHeight(double w) { super.SetWidth(w); super.SetHeight(w); } }
一般来讲继承关系就是is-a的关系,若是一个对象A is-a另外一个对象B,那么能够说这个对象A就是从另外一个B继承而来。ip
很显然一个正方形is-a长方形,因此知足这种继承关系。ci
可是因为正方形4边相等,没有所谓的长宽之分,因此它对setWidth和setHeight作了修改来规避长宽问题。it
这个时候当正方形的一个宽发生改变,长也会相应的改变,来实现正方形的4边相等。io
public void g(Rectangle r) { r.SetWidth(5); r.SetHeight(4); Assert.AreEqual(r.GetWidth() * r.GetHeight(), 20); }
可是这个时候执行g(Rectangle r) 方法就会出现问题。
上述例子明显的违反了LSP原则,也潜在的违背了OCP原则。
从孤立的角度看,一个模型没法本身进行有意义地验证。模型的正确性仅能经过它的使用者来表达。例如,孤立地看 Square 和 Rectangle,咱们发现它们是自洽的而且是有效的。但当咱们从一个对基类作出合理假设的程序员的角度来看待它们时,这个模型就被打破了。
结论:
OCP是OOD的核心,而LSP则是OCP的主要原则之一,正是子类的可替换性才使得使用基类类型的模块在无需修改的状况下就能够拓展。
术语is-a的范围过于普遍,有上述例子致使该术语不能有效的定义子类。因此以为子类的定义应该是“可替换性”。