就像哺乳动物类有行走的行为,所有子类都应该遵守。
但是很少有像海豚和蝙蝠这样的哺乳动物没有这种行为。
我们如何实现这一点?
在我看来,所有子类都应该遵守与超类相关的所有行为。
任何帮助表示赞赏。谢谢!
就像哺乳动物类有行走的行为,所有子类都应该遵守。
但是很少有像海豚和蝙蝠这样的哺乳动物没有这种行为。
我们如何实现这一点?
在我看来,所有子类都应该遵守与超类相关的所有行为。
任何帮助表示赞赏。谢谢!
Mammal 类应该只定义所有哺乳动物的共同特征,正如你所说的那样,步行不是一个共同特征。
可以使用接口添加行为,如下例所示
class abstract Mammal {
abstract void regulateTemperature();
}
interface CanFly {
void land();
void takeOff();
}
class Bat extends Mammal implements CanFly {
}
抱歉,如果我犯了语法错误,我的 Java 有点生疏,但你明白了,在你的基类中尽可能通用。这就是说我同意@dystroy,在动物领域获得正确的继承太难了。您可能想尝试为一盏灯或一件衬衫建模,从比这更简单的方式开始。
你的断言相互矛盾。
要么所有子类都具有行为,要么并非所有子类都具有行为。你不能两者兼得。
在面向对象的设计中,所有子类都支持其超类的契约是很有用的,这样任何子类的实例都可以在引用超类的任何地方使用。这被称为Liskov 替换原则。
您刚刚发现了传统继承和 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
您的示例中未正确定义 Mammal 类,因为并非所有哺乳动物都可以行走。它不应该包含walk
方法。在这种情况下,我会选择步行界面,游泳和飞行界面也适用于其他用于移动的方法。
如果您将 Mammal 定义为具有 Walk() 方法,那么您是在说所有哺乳动物都可以行走。
Dolphin 的实现可能如下所示:
public void Walk()
{
throw new TraitLossException();
}
免责声明:这个答案不是关于好的设计,而是关于现有的实践。
有时,您的子类不能(或只是不会)提供超类提供的所有服务。一个突出的例子是 Iterator.remove(),它可以实现也可以不实现。当标准库中出现这种情况时,通常会抛出 UnsupportedOperationException。在某些情况下,例如迭代器,在某种意义上甚至是合同的一部分,不支持该操作的实现应该抛出异常。
这是对非抽象类进行子类化可能有意义的情况之一。
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());
}
(请注意,我们在这里对物种类型和特定动物存在一些混淆。同样值得注意的是,如果你把曾经存在的每一种动物都拿走,没有物种界限。)
很简单,使用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() { ... }
}