2

我有点进退两难。我有 class animal,假设它存储基本的东西,如位置等。所以我有一个smartAnimal扩展的类animal。假设smartAnimal添加了一些无需用户输入即可做出决策的功能。

现在,我有一个dog扩展类animal。它不会扩展smartAnimal,因为它不需要该功能。到目前为止我很好: adog是一个animal并且 asmartAnimal是一个animal。但现在我希望smartDog扩展smartAnimalsmartDog也应该是一个dog. 例如,常规中的很多功能,dog比如说.sniff(), .poop(),并且.bark()也应该在我的smartDog,但除非我从字面上复制+粘贴代码,否则它不会是,因为 Java 不允许多重继承。

组合似乎不优雅,因为如果我有:

class smartDog{ smartAnimal thisSmartAnimal; dog thisDog; }

...我会在 中复制“东西” animal,例如,位置。我将不得不处理两组位置变量!以及 中的任何属性的副本animal

继承多个接口听起来也不是正确的解决方案,因为假设dog是一个接口,.sniff(),.poop().bark()的实现不应该改变和重新实现smartDog以及任何其他类

这里的最佳做法是什么?也就是说,有两个类dogsmartDog

编辑:

从一些评论/答案中,让我澄清一下。在我的具体项目中,asmartAnimal实际上有一个完整的神经网络来控制它。这是很多代码,将其抽象为接口是没有意义的。不管是什么动物,神经网络功能的核心都是一样的,但每个smartAnimal子类都会以不同的方式实现人工智能“大脑”的输出。相反,每只动物都有自己的功能,无论是人类控制它还是它自己的人工智能代理控制它,它们的功能都是一样的。

4

3 回答 3

3

答案是这不是一个现实的继承层次结构,你可以从你使用“添加一些功能”这个词来描述在子类中添加方法的事实中看出这一点。这不是正确的继承。在适当的继承中(至少在 Java 中),每个方法都应该存在于继承层次结构的顶层。继承是为了代码重用,而不是在你深入树时添加功能。因此,给定的问题并没有真正的答案。

于 2013-02-24T23:53:15.393 回答
2

我认为您可能正在寻找的是名为“默认实现”的新 JDK 8 功能

我认为没有这个的明智解决方案是让狗继承 smartAnimal。因此:smartDog 是一只狗,它是一种 smartAnimal,它是一种动物。

很难获得更精确的建议,因为它实际上取决于您的对象正在实现什么。(例如,它们是否都有内部状态?或者它们只是定义新行为?)

于 2013-02-24T23:49:23.343 回答
2

由于我们在这里讨论的是Java,因此模型是具有多个接口的单继承。

话虽如此,鉴于这些示例,正确的抽象级别是合适的。也就是说,答案在于以下组合:

  1. 正确的继承(参见 GOF 书籍中关于“is a”、“has a”和行为)。如果你发现自己说“狗很聪明”——那可能是狗的行为与“狗是哺乳动物”的对比(注意名词与形容词)。“聪明”的狗表现出与哑巴不同的某些行为,但从数据建模的角度来看,两者都是“狗”。
  2. 适当的聚合。很多时候,我发现将复杂的“事物”分解成它们的组成部分很有用。因此,“汽车”由发动机、变速箱、底盘等组成。狗有毛皮(有颜色、质地等)、腿、头、身体形状等,当区分狗是什么和它的行为方式(智能 = 界面)。
  3. 抽象接口。在此示例中可能具有挑战性的是,“智能”可能在不同类型的对象/名词之间有所不同。“智能”狗可能能够理解命令,而“智能”手机具有某些功能,例如电子邮件。因此,“智能”可能不是最高级别的适当接口,但可能与“哺乳动物”相关联->“狗”是哺乳动物可能实现 Mammal.Smart 接口(特定于哺乳动物)。

这确实是信息建模和整个计算机科学中比较困难和重要的方面之一。整组书籍和研究都致力于这一主题,因此可能不适合作为 Stack Overflow 问题,旨在为直截了当的简洁问题提供直截了当、简单的答案。

于 2013-02-24T23:54:42.697 回答