liskov替换原则
这项原则是由芭芭拉·里斯科夫 ( Barbara Liskov)于1988年撰写的。
这里的想法是,子类型对于超类型引用必须是可替换的,而又不影响程序执行。
此原则与开放式封闭原则 (OCP)密切相关,违反LSP则违反了OCP。 让我解释:
如果子类型不能替代超类型引用,那么为了支持子类型实例,我们继续对现有代码进行更改并添加支持。 这显然违反了OCP。
在我们进行运行时类型识别然后将其转换为适当的引用类型的地方,通常会看到这种情况。 而且,如果我们添加新的子类型实现,则必须编辑代码以测试新子类型的实例。
让我举一个微妙的例子:
class Bird {
public void fly(){}
public void eat(){}
}
class Crow extends Bird {}
class Ostrich extends Bird{
fly(){
throw new UnsupportedOperationException();
}
}
public BirdTest{
public static void main(String[] args){
List<Bird> birdList = new ArrayList<Bird>();
birdList.add(new Bird());
birdList.add(new Crow());
birdList.add(new Ostrich());
letTheBirdsFly ( birdList );
}
static void letTheBirdsFly ( List<Bird> birdList ){
for ( Bird b : birdList ) {
b.fly();
}
}
}
您认为执行此代码会发生什么? 一旦鸵鸟实例通过,它就会炸毁!!! 在此,子类型不可替换为超级类型。
我们如何解决此类问题?
通过使用分解。 有时,将公共功能分解为单独的类可以帮助创建确认LSP的层次结构。
在上述情况下,我们可以将飞行功能分解为“飞行”和“非飞行”鸟类。
class Bird{
public void eat(){}
}
class FlightBird extends Bird{
public void fly()()
}
class NonFlight extends Bird{}
因此,除了处理“鸟类”以外,我们还可以处理“飞行”和“非飞行”两类鸟类。
我们如何识别LSP违规?
与基类相比,派生类可能需要的功能更少,因此某些方法将是多余的。
我们可能使用IS-A来检查Super-Sub关系,但是LSP不仅使用IS-A,而且还要求Sub类型必须可以替代Super类。 并且不能孤立地确定子类的可替代性。 必须考虑类层次结构的客户端将如何使用它。
Robert Martin在LSP上的详细论文 。
参考:来自我们的JCG合作伙伴 Mohamed Sanaulla的 SOLID- Liskov替代原理 ,在“ Experiences Unlimited”博客中 。
翻译自: https://www.javacodegeeks.com/2011/11/solid-liskov-substitution-principle.html
liskov替换原则