就像有一个哺乳动物类有行走的行为,所有子类都应该遵守。
但很少有像海豚和蝙蝠这样的哺乳动物没有这种行为。
我们如何实现这个目标?
按照我的说法,所有子类都应该遵守与超类相关的所有行为。
感谢任何帮助。谢谢!
答案 0 :(得分:6)
哺乳动物类应该只为所有哺乳动物定义共同的特征,正如你所说,行走不是一个常见的特征。
可以使用接口添加行为,如下例
class abstract Mammal {
abstract void regulateTemperature();
}
interface CanFly {
void land();
void takeOff();
}
class Bat extends Mammal implements CanFly {
}
很抱歉,如果我犯了语法错误,我的Java有点生疏,但是你有了这个想法,就像你在基类中一样通用。这就是说我同意@dystroy,在动物领域获得继承是很困难的。你可能想尝试一下灯或衬衫的造型,从比这更简单的方法开始。
答案 1 :(得分:2)
你的断言相互矛盾。
要么所有子类都有行为,要么都没有行为。你不能兼得。
在面向对象的设计中,所有子类都支持其超类的契约是很有用的,这样任何子类的实例都可以在引用超类的任何地方使用。这称为Liskov substitution principle。
答案 2 :(得分:2)
您刚刚发现了传统继承和OOP概念的根本问题。即使是最微不足道的例子,对象分类为严格的类别也是非常困难的(有趣的是,分类是智商测试的重要组成部分)。在研究动物王国的例子时,很快就会发现,将时间分组为严格的,自上而下的,细分的类别是没有意义的。将这个想法与编程相结合并尝试重用功能,最终可能会自杀。
现代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
答案 3 :(得分: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() { ... }
}
答案 4 :(得分:0)
在你的例子中没有正确定义哺乳动物类,因为并非所有的哺乳动物都可以行走。它不应包含walk
方法。在这种情况下,我会选择步行界面,其中游泳和飞行界面也适用于其他用于移动的方法。
答案 5 :(得分:0)
如果你将Mammal定义为使用Walk()方法,那么你就说所有的哺乳动物都可以走路了。
您对Dolphin的实施可能如下所示:
public void Walk()
{
throw new TraitLossException();
}
答案 6 :(得分:0)
免责声明:这个答案不是关于良好的设计,而是关于现有的实践。
有时候,你有一个不能(或根本不会)提供超类提供的所有服务的子类。一个突出的例子是Iterator.remove(),它可以实现也可以不实现。当标准库中出现这种情况时,通常会抛出UnsupportedOperationException。在某些情况下,就像Iterator一样,在某种意义上,即使是不支持该操作的实现也应该抛出异常,甚至是合同的一部分。
答案 7 :(得分: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());
}
(注意我们在这里对物种类型和特定动物存在一些混淆。另外值得注意的是,如果你采取任何曾经存在的动物,就没有物种界限。)