4

就像哺乳动物类有行走的行为,所有子类都应该遵守。

但是很少有像海豚和蝙蝠这样的哺乳动物没有这种行为。

我们如何实现这一点?

在我看来,所有子类都应该遵守与超类相关的所有行为。

任何帮助表示赞赏。谢谢!

4

8 回答 8

6

Mammal 类应该只定义所有哺乳动物的共同特征,正如你所说的那样,步行不是一个共同特征。

可以使用接口添加行为,如下例所示

class abstract Mammal {

    abstract void regulateTemperature();

}

interface CanFly {

    void land();
    void takeOff();

}

class Bat extends Mammal implements CanFly {

}

抱歉,如果我犯了语法错误,我的 Java 有点生疏,但你明白了,在你的基类中尽可能通用。这就是说我同意@dystroy,在动物领域获得正确的继承太难了。您可能想尝试为一盏灯或一件衬衫建模,从比这更简单的方式开始。

于 2013-07-10T13:32:28.360 回答
2

你的断言相互矛盾。

  • 就像哺乳动物类有行走的行为,所有子类都应该遵守。
  • 但是很少有像海豚和蝙蝠这样的哺乳动物没有这种行为。

要么所有子类都具有行为,要么并非所有子类都具有行为。你不能两者兼得。

在面向对象的设计中,所有子类都支持其超类的契约是很有用的,这样任何子类的实例都可以在引用超类的任何地方使用。这被称为Liskov 替换原则

于 2013-07-10T13:32:23.657 回答
2

您刚刚发现了传统继承和 OOP 概念的根本问题。即使在最微不足道的例子中,将对象分类为严格的类别也是极其困难的(有趣的是,分类是 IQ 测试的重要组成部分)。在研究动物王国的例子时,很快就会发现,将时间划分为严格的、自上而下的、细分的类别是没有意义的。将此想法与编程相结合并尝试重用功能,您最终可能会自杀。

现代 OOP 避免使用继承来重用代码,而是利用它来实现多态性。深层继承树很脆弱,被认为是不好的做法。相反,代码重用是通过聚合来实现的。小对象及其行为被混合和匹配以创建更复杂的对象。使用依赖注入和基于策略的设计等概念可以增强此行为。

有关这些概念的更多信息和实际应用,请阅读:

http://en.wikipedia.org/wiki/Composition_over_inheritance

http://en.wikipedia.org/wiki/Aspect-oriented_programming

http://en.wikipedia.org/wiki/Component-based_software_engineering

http://en.wikipedia.org/wiki/Policy-based_design

http://en.wikipedia.org/wiki/Dependency_injection

于 2013-07-11T02:19:14.570 回答
0

您的示例中未正确定义 Mammal 类,因为并非所有哺乳动物都可以行走。它不应该包含walk方法。在这种情况下,我会选择步行界面,游泳和飞行界面也适用于其他用于移动的方法。

于 2013-07-10T13:34:12.113 回答
0

如果您将 Mammal 定义为具有 Walk() 方法,那么您是在说所有哺乳动物都可以行走。

Dolphin 的实现可能如下所示:

public void Walk()
{
    throw new TraitLossException();
}

http://www.nescent.org/science/awards_summary.php?id=24

于 2013-07-10T13:35:34.107 回答
0

免责声明:这个答案不是关于好的设计,而是关于现有的实践。

有时,您的子类不能(或只是不会)提供超类提供的所有服务。一个突出的例子是 Iterator.remove(),它可以实现也可以不实现。当标准库中出现这种情况时,通常会抛出 UnsupportedOperationException。在某些情况下,例如迭代器,在某种意义上甚至是合同的一部分,不支持该操作的实现应该抛出异常。

于 2013-07-10T13:37:35.320 回答
0

这是对非抽象类进行子类化可能有意义的情况之一。

class Mammal {
    ...
    /** May not walk. This implementation succeeds. */
    void walk() {
        ... do some walking ...
    }
}

class WateronlyMammal extends Mammal {
    @Override void walk() {
        ... sit there looking sad ...
    }
}

然后将动物类型创建为new Mammal("Dog")new WateronlyMammal("Dolphin")

或者,您可能想要组合而不是继承,它会用冗长来换取更简单的组件。

 interface Walker {
     /** May not walk. */
     void walk();
 }
 final class Mammal {
     public Mammal(String speciesName, Walker walk) {
         ...
     }
     ...
 }

创建为new Mammal("Dog", competentWalker())new Mammal("Dolphin", notSoGoodWalker())

甚至可以添加便利构造函数:

     public Mammal(String speciesName) {
         this(speciesName, competentWalker(), poorFlyer());
     }

(请注意,我们在这里对物种类型和特定动物存在一些混淆。同样值得注意的是,如果你把曾经存在的每一种动物都拿走,没有物种界限。)

于 2013-07-10T14:21:54.557 回答
0

很简单,使用Walking可用于行走动物的界面。

例如:

interface Walking {
    public abstract void walk();  // implementing classes must implement this
}

class Cow extends Mammal implements Walking {
    public void walk() { ... }
}

class Dolphin extends Mammal {
    public void swim() { ... }
}

class Bat extends Mammal {
    public void fly() { ... }
}
于 2013-07-10T13:30:48.967 回答