里式替换原则其实就是前面提到的开闭原则更严格的补充,除了有开闭原则带来的优势外,也保证了继承中重写父类方法造成的可复用性变差与稳定性变差的问题。
里式替换原则在实际编中主要应用在类的组织结构上,对于继承的设计,子类不可以重写父类的方法,只能为父类添加方法。如果在设计的时候,发现子类不得不重写父类的方法,则表明类的组织结构有问题,需要重新设计类的继承关系。
假设现在有一个鸟(Bird)的类,一个鸵鸟( Ostrich)的类,鸵鸟( Ostrich)继承自鸟(Bird)类
鸟有基本的飞行能力,但是鸵鸟不能飞,只能奔跑
class Bird{
var name : String
init(name : String) {
self.name = name
}
func fly() {
print("\(self.name)开始飞行")
}
}
//创建并且调用飞的方法
let bird = Bird(name: "鸟")
bird.fly()
创建鸵鸟( Ostrich)类的时候,不能飞行只能奔跑,所以只能这样写
class Ostrich : Bird{
override func fly() {
print("\(self.name)不能飞行")
}
func run() {
print("\(self.name)开始奔跑")
}
}
let ostrich = Ostrich(name: "鸵鸟")
ostrich.fly() //鸵鸟不能飞行
ostrich.run() //鸵鸟开始奔跑
由于里式替换原则,子类不能重写父类的方法或者属性
所以,Ostrich这个类的这里违背了该原则。但在此场景中,子类没办法不去重写父类的方法,这说明我们这个设计有问题。
override func fly() {
print("\(self.name)不能飞行")
}
所以我们需要对该组织的设计重新定义
我们需要新定义一个父类Animal,把原来Bird类的属性和方法抽象出来,好让我们的设计遵从里式替换原则
class Animal{
var name : String
init(name : String) {
self.name = name
}
}
这里,我们把Bird类的name抽象了出来,在父类Animal实现,并且让Ostrich和Bird同时继承Animal
代码就变成了这个样子
class Bird : Animal{
func fly() {
print("\(self.name)开始飞行")
}
}
//创建并且调用飞的方法
let bird = Bird(name: "鸟")
bird.fly()
class Ostrich : Animal{
func run() {
print("\(self.name)开始奔跑")
}
}
let ostrich = Ostrich(name: "鸵鸟")
ostrich.run() //鸵鸟开始奔跑
以上为里式替换原则
网友评论