例如,我有一个像这样实现的抽象类:
public abstract class Animal
{
public abstract void makeNoise();
}
我有一个儿童班,代表一种不会产生任何噪音的动物。哪个更好?
public class Turtle extends Animal
{
// properties and methods
public void makeNoise()
{
//leave it empty
}
}
或者我应该简单地做到:public abstract void makeNoise();
在Turtle里面?
答案 0 :(得分:6)
最好将makeNoise()
方法移出Animal
,因为所有动物都不会产生噪音。因此,创建另一个接口NoiseMaker
并在其中添加makeNoise
方法。
public abstract class Animal {
// animals methods
}
public interface NoiseMaker {
void makeNoise();
}
public class Turtle extends Animal {
// properties and methods which are applicable for turtle
}
当你想要一只像狮子一样发出噪音的动物时,你可以扩展Animal
类并实现NoiseMaker
,这样它就具有动物的行为以及产生噪音。
public class Lion extends Animal implements NoiseMaker {
public void makeNoise() {
// implementation
}
// other properties and methods which are applicable for turtle
}
答案 1 :(得分:3)
人们经常做的事:抛出某种异常,例如UnsupportedOperationException
或类似的东西。
但是:最后你正在修复症状。
重点是:扩展基类意味着基类的派生类 IS-A 对象也是如此。而且你在问:如何违反基类的公共合同。
答案是:你应该不这样做。干净利落。
因为如果你开始在这里抛出异常,突然之间,可能有List<Animal> animals
的调用者不能在每个对象上调用makeNoise()
。相反,调用者使用instanceof
(这样他就可以避免在特定类上调用makeNoise()
) - 或者需要try / catch。
所以真正的答案是:退后一步,改进你的模型。确保基类上的所有方法都适用于派生类。如果不是 - 可能会引入另一个层,例如abstract class NoisyAnimal extends Animal
。
答案 2 :(得分:2)
这是使用UnsupportedOperationException
由于抽象设计,你必须实现。所以只需实现该方法并抛出UnsupportedOperationException
异常。
保持动物,因为大多数动物都会发出声音:)如果你把它移到Turtle,所有的子类都必须有自己的声音方法。
答案 3 :(得分:2)
或者我应该简单地制作它:
public abstract void makeNoise();
内的Turtle
?
如果你这样做,Turtle
是抽象的。所以问题不是哪个更好,问题是,您是否希望能够实例化Turtle
?
如果这样做,则必须实施该方法。
如果您对它是抽象的可以,那么将它声明为抽象并且根本不列出该方法:
public abstract class Turtle extends Animal {
}
答案 4 :(得分:1)
您可能想区分动物是否发出噪音。
的长篇大论public abstract class Animals {}
public abstract class AnimalsNoisy extends Animals { abstract void makeNoise(); }
然后您将使用Turtle extends Animals
。这种结构的优点是,如果你有一个动物清单,你不必担心,如果他们实施了makeNoise
方法,或者不是。
for(AnimalsNoisy animal: ListAnimalsNoisy) { animal.makeNoise();}
答案 5 :(得分:0)
你可能会这样写,这是你想要的吗?
C.a
C.b
答案 6 :(得分:0)
这是学习如何使代码松散耦合的一个很好的例子 通过松散耦合,我的意思是,如果您决定更改或修改代码,则不会触及以前的代码。有时它被称为OPEN-CLOSE原则 首先,您必须确定代码的哪些部分经常更改 这里的方法 makingNoise()将根据您的类具有不同的实现。
这种设计可以通过以下步骤实现。
1)创建一个将具有makeNoise()实现的接口 方法
public interface NoiseInterface {
public void speak();
}
2)为NoiseInterface创建具体实现
例如:For Fox
public class FoxSound implements NoiseInterface {
@Override
public void speak()
{
//What does the fox say ?
Sysout("chin chin chin tin tin tin");
}
}
3:提供动物类噪声接口
public abstract class Animal
{
public NoiseInterface noiseMaker;
public abstract void makeNoise();
}
4:只需在Fox Class中提供您选择的NoiseInterface类型
public class Fox extends Animal
{
public Fox()
{
noiseMaker = new FoxSound();
}
public void makeNoise()
{
noiseMaker.speak();
}
}
现在关于这个设计的惊人之处在于你永远不必担心这个设计。我会解释你是怎么做的。
您只需致电
Animal me = new Fox();
fox.makeNoise();
现在将来你想要让Fox静音。 您将创建一个新的接口静音
public class Mute implements NoiseInterface {
@Override
public void speak()
{
Sysout("No sound");
}
}
只需更改Fox类构造函数中的NoiseBehavior
即可noiseMaker = new Mute();
您可以在 OPEN-CLOSE 原则Here
上找到更多信息