java - 接口(interface)和继承——一个面向对象的设计困境

标签 java oop inheritance

我无法理解何时/为什么实现继承以及何时/为什么通过接口(interface)实现继承。当我解释时,请耐心等待。

假设我们有一个父类 Animal我们希望用 3 个子类扩展它:Dog , CatMouse .

假设所有动物都能够eat() , sleep() , scratch()move() .和 Dog能够pant() .有了这些知识,我们将继续将前 4 个行为添加到 Animal 中。父类(super class)并拥有 Dog , CatMouse延长 Animal .我们还将添加方法 pant()Dog仅限 bec 类的狗 pant() .

现在如果我们想添加另一个名为 waggleTail() 的方法会发生什么?但只有 CatDog表现出这种行为。我们无法将此行为添加到 Animal bec然后Mouse还将继承行为(并且鼠标不会摆动它的尾部)。另一种方法是添加方法 waggleTail()DogCat类但不是 Mouse类(class)。然而,这种方法没有意义,因为我们会通过编写方法 waggleTail() 违反 DRY 原则(不要重复自己)。两次。我们希望每个方法都写一次,而且只写一次。

也许我们可以通过创建一个继承自 Animal 的新子类来解决这个问题。叫 TailWagglingAnimal , 添加方法 waggleTail()到这个子类然后同时拥有 DogCat从这个新的子类继承。这听起来很合理,直到您意识到还有许多其他这样的异常,并且我们必须一次又一次地为每个异常重复这个过程(这会无限扩展继承层次结构)。

此外,如果我们有特定类型的 Dog 怎么办? (让我们称他为“Coton de Tulear”)表现出 Dog 的所有其他行为(例如喘气),只是它不摇尾部。如果我们直接从 Animal 继承“Coton de Tulear”它将无法喘气()。如果我们让它继承自 Dog它可以摆动它的尾部(bec Dog 延伸 TailWagglingAnimal)。如果我们有 Dog延长 Animal直接然后创建一个名为 TailWagglingDog 的新子类(如 TailWagglingAnimal )那么 Cat 将无法继承此行为(因此我们需要在违反 DRY 原则的 Cat 层次结构中的某处复制该行为)。

我们做什么?

基于 stackoverflow 上的数十个线程(以及几本 OO 设计书籍),建议删除方法 waggleTail()从 Dog 类并将其添加到和接口(interface)。我们调用接口(interface)TailWaggler然后让所有的狗(除了“Coton de Tulear”)实现这个接口(interface)。但是,我无法理解为什么/如何使用它。

如果你仔细想想,这意味着所有 50+ 条狗面包(假设有 50 条狗面包需要表现出这种行为)都需要添加工具 TailWaggler关键字只是一种 Dog不会表现出这种行为。这不仅意味着程序员需要进行大量额外的手动工作(在每个类的开头添加工具 TailWaggler),还意味着所有后代都需要关注他们行为的所有小细节。展示(如果我们将此行为添加到父类并扩展父类,则不会出现这种情况)。如果我们只有几个这样的案例,这可能没问题,但如果我们有几十个或几百个这样的案例呢?最后,当我们添加新类型的狗的子类时,最终会出现一种 Dog是另一个不会表现出 Dog 父类的行为之一 - 所以这意味着我们需要缓慢但肯定地需要从(父)Dog 中删除几乎所有的行为。类并将它们添加到接口(interface)?然后我们需要确保所有的子类都实现了许多不同的接口(interface)。有人可能会建议我们将所有相关的行为组合在一个界面中,但这只有在不同狗表现出的行为是一致的情况下才有可能 - 如果不是这种情况怎么办?)

谢谢!

最佳答案

We'd then need to make sure all of the sub classes implement dozens of different interfaces


  • 如果您的类需要实现太多接口(interface),请检查它是否违反单一职责原则。考虑将类(class)分成更小的类(class)。
  • 实现几个小接口(interface)而不是一个大接口(interface)符合接口(interface)隔离原则,这会导致一些积极的后果。

  • it means that all descendants need to be concerned with all of little and petty details of the behavior they exhibit



    这更多是关于实现困难。多重继承或自动委托(delegate)可以在这里提供帮助。由于我们在 Java 中没有,我们必须在其他选项之间进行选择:
  • 为每个类手动实现委托(delegate):(
  • 如果实现不复杂,请使用 Java 8 接口(interface)。
  • 使用代码生成库自动生成委托(delegate)代码(例如查看 lombok 库 @Delegate 功能 https://projectlombok.org/features/experimental/Delegate.html)
  • 关于java - 接口(interface)和继承——一个面向对象的设计困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42727052/

    相关文章:

    .net - 衡量面向对象的指标

    java - 按子类 Java 中的类型对通过继承创建的数组进行排序

    java - Android通过不同的进程非 Activity 类通知应用程序

    java - Vaadin TextArea 键盘监听器消费事件

    java - 无效的方法声明;需要返回类型

    Java 程序设计布局建议?

    c# - 如何访问继承Collection<>的类中的集合?

    java - 如何修复java错误?

    java - concat Jolt 转换可在演示站点上运行;在代码中不起作用

    java - 使用 .contains 方法忽略大小写的选项?