Liskov替代原则(LSP)和界面分离原则(ISP)之间有什么核心区别吗?最终,这两种方法都是为了设计具有通用功能的界面,并在您具有特殊功能时引入新的界面。
LSP管理父类和子类之间的关系(即层次关系)。它告诉您如何实现API。
ISP管理父类和客户端类之间的关系(即生产者/消费者关系)。它告诉您何时实现API。
考虑一个有一百种方法的接口。一个子类可以实现所有100个,而不违反其中任何一个定义的契约,从而满足Liskov替换;但是很难想象每个客户端都需要所有这些方法,所以接口隔离几乎肯定会被违反。
相反,只有一种方法的接口肯定满足接口分离;但是,如果一个实现不遵守这个方法契约,那么就违反了Liskov替换。
另见:LSP与DIP
两者都是坚实的原则
Device
类,它有一个函数callBaba()
,该函数获取您父亲的电话号码,然后给他打电话,那么您必须确保Device
的所有子类中的callBaba()
方法执行相同的任务。如果Device
的任何子类在callBaba()
中有其他行为,则表示您破坏了LSP违反Liskov原则的代码示例。
class Device {
func callBaba() {
print("I will find your father and I will call him")
}
}
class Calculator: Device {
override func callBaba() {
print("Sorry, I don't have this functionality ")
}
}
解决方案
interface CanCall {
func callBaba()
}
class Device {
// all basic shared functions here.
}
class Calculator: Device {
// all functions that calculator can do + Device
}
class SmartPhone: Device implements CanCall {
// all smartphone stuff
func callBaba() {
print("I will find your father and I will call him")
}
}
这违反了ISP原则,因为它有两种不同的责任
protocol Animal {
func fly()
func eat()
}
解决方案
protocol Flyable {
func fly()
}
protocol Feedable {
func eat()
}
LSP:接收者必须履行其promise的合同。
ISP:呼叫者不应该过分依赖接收器的接口。
适合的地方:如果应用ISP,则只使用接收器完整接口的一部分。但根据LSP的规定,接受者仍然必须尊重这一部分。
如果您未能申请ISP,可能会有违反LSP的诱惑。因为“这个方法不重要,它实际上不会被调用。”
我在理解这两个原则时有些困难。这是一个有点长的阅读问题,所以要有耐心。 假设我们有一个类 和接口 然后我们创建了两个子类 现在我们将使implements 并在儿童课程中做出改变 并为该结构创建测试函数(如下LSP): 在这里我想停下来,因为实际上在下一步我被绊倒了。如果我们要创建第三个类? 圆没有边,所以为这个孩子实现听起来很可笑。好的,我们可以只将实现移到四边形和三角形,但在这种情况下LSP将
我试图通过反复阅读维基百科条目来确定我对上述原则的理解。 撇开仍然让我悲伤的协变和逆变的概念不谈,wikipedia还提到超类型的不变量必须保留在子类型和历史约束或历史规则中。基于最后两个概念,我提出了一个小例子: 所以我的问题是:基于上述两个概念,我用这个例子是否违反了原则?若否,原因为何? 事先非常感谢。
来自维基百科, Liskov的行为子类型概念定义了对象的可替代性概念;也就是说,如果S是T的子类型,则程序中T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性(例如正确性)。 假设以下类层次结构: 基本抽象类-。它有一个只读属性,在后继程序中被重写。 基类的继承者-,它重写并返回灰色。 Cat的继任者-,它覆盖并返回带条纹的。 然后我们声明一个方法,参数类型为(不是)。 向该方法发送
在创建我的班级结构时,我努力坚持利斯科夫替代原则。我想在Day类中存储一组日历项。需要有几种不同类型的日历项,例如: 任命项目 备注项目 轮换项目 它们都共享一些抽象基类CalendarItem中的常见功能: 但例如RotaItem有一些额外的功能: 其他类也添加了自己的逻辑等。 我有一组CalendarBaseItem用于我的日课: 但在回顾这一点时,我可以看到我正在打破LSP原则,因为我必须检
存在无法写入或查找的流派生类这一事实是否违反了Liskov替换原则? 例如,无法查找NetworkStream,如果调用方法,它将抛出。 还是因为存在标志就可以了? 考虑到众所周知的继承自的例子...将标志和添加到是否可以解决问题? 这难道不是打开了通过添加旗帜来解决问题的大门吗?
假设我有一个抽象类鸟,它的一个函数是飞(int高度)。 我有许多不同的鸟类,每个类都有自己不同的飞的实现,这个函数在整个应用程序中被广泛使用。 有一天,我的老板来了,要求我添加一只鸭子,它做其他鸟类所做的一切,只是它不飞,而是在应用程序的池塘里游泳。 将duck添加为bird的子类型违反了Liskov替换规则,因为在调用duck时。我们要么抛出异常,要么什么也不做,要么违反正确性原则。 在牢记坚实