当前位置: 首页 > 知识库问答 >
问题:

liskov替代原理与界面分离原理的区别

洪宇定
2023-03-14

Liskov替代原则(LSP)和界面分离原则(ISP)之间有什么核心区别吗?最终,这两种方法都是为了设计具有通用功能的界面,并在您具有特殊功能时引入新的界面。

共有3个答案

习狐若
2023-03-14

LSP管理父类和子类之间的关系(即层次关系)。它告诉您如何实现API。

ISP管理父类和客户端类之间的关系(即生产者/消费者关系)。它告诉您何时实现API。

考虑一个有一百种方法的接口。一个子类可以实现所有100个,而不违反其中任何一个定义的契约,从而满足Liskov替换;但是很难想象每个客户端都需要所有这些方法,所以接口隔离几乎肯定会被违反。

相反,只有一种方法的接口肯定满足接口分离;但是,如果一个实现不遵守这个方法契约,那么就违反了Liskov替换。

另见:LSP与DIP

张亦
2023-03-14

两者都是坚实的原则

  • LSP(Liskov替换):该原则要求您确保所有子类都具有与父类相同的行为。例如:如果您有一个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(接口隔离):要求您为不同的职责创建不同的接口,换句话说,不要将不相关的行为分组到一个接口中,如果您已经有一个具有多个职责的接口,那么您就破坏了ISP,并且实现者不需要所有这些东西

这违反了ISP原则,因为它有两种不同的责任

  protocol Animal {
        func fly()
        func eat()
    }

解决方案

protocol Flyable {
    func fly()
}
protocol Feedable {
    func eat()
}
阳建弼
2023-03-14

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时。我们要么抛出异常,要么什么也不做,要么违反正确性原则。 在牢记坚实