Java 抽象方法实现(如果未使用)
例如,我有一个抽象类实现如下:Java 抽象方法实现(如果未使用),java,Java,例如,我有一个抽象类实现如下: public abstract class Animal { public abstract void makeNoise(); } 我有一个儿童类,它代表一种不会发出任何噪音的动物。哪个更好 public class Turtle extends Animal { // properties and methods public void makeNoise() { //leave it empty } } 或者我应该
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()代码>海龟内部 这是使用UnsupportedOperationException
由于抽象的设计,您必须实现。因此,只需实现该方法并抛出UnsupportedOperationException
exception
让它成为动物,因为大多数动物都会发出声音:)如果你把它移到海龟身上,所有的子类也必须有自己的发声方法
或者我应该简单地说:public abstract void makeNoise()代码>内部海龟
如果你这样做,Turtle
是抽象的。所以问题不是哪一个更好,问题是,您是否希望能够实例化Turtle
如果您这样做,您必须实现该方法
如果您同意它是抽象的,那么将其声明为抽象的,并且根本不列出该方法:
public abstract class Turtle extends Animal {
}
最好将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
}
人们经常做的事情:抛出某种异常,比如UnsupportedOperationException
或类似的东西
但是:最后,您正在修复一个症状
要点是:扩展基类意味着派生类的对象也是基类的对象。你在问:如何违反基类的公共契约
答案是:你不应该那样做。简单明了
因为如果您开始在这里抛出异常,那么突然之间,可能有列表动物的调用方就不能简单地对每个对象调用makeNoise()
。调用者必须使用instanceof
(这样他就可以避免在特定类上调用makeNoise()
),或者需要try/catch
因此,真正的答案是:后退一步,改进你的模型。确保基类上的所有方法对于派生类都有意义。如果没有-可能会引入另一层,比如抽象类noiseAnimal extends Animal
,您可能需要区分发出噪音的动物与否。一长串的东西
public abstract class Animals {}
public abstract class AnimalsNoisy extends Animals { abstract void makeNoise(); }
然后您将使用海龟扩展动物
。这种结构的优点是,如果你有一个动物列表,你不必担心它们是否实现了makeNoise
方法,例如
for(AnimalsNoisy animal: ListAnimalsNoisy) { animal.makeNoise();}
你可以这样写,这是你想要的吗
public interface NoiseInterface {
void makingNoise();
void makingNoNoise();
}
public class Animal implements NoiseInterface{
@Override
public void makingNoise() {
System.out.println("noising");
}
@Override
public void makingNoNoise() {
System.out.println("slient");
}
}
public class Turtle extends Animal{
@Override
public void makingNoNoise() {
System.out.println("turtle");
super.makingNoNoise();
}
}
这是一个学习如何使代码松散耦合的好例子。
所谓松散耦合,我的意思是,如果您决定更改或修改您的代码,您将不会触及以前的代码。有时它被称为开闭原则。
首先,您必须确定代码的哪些部分经常更改。
这里,方法makingNoise()将根据您的类具有不同的实现
此设计可通过以下步骤实现
1) 创建一个接口,该接口将包含makeNoise()的实现
方法
2) 创建NoiseInterface的具体实现
给福克斯的
public class FoxSound implements NoiseInterface {
@Override
public void speak()
{
//What does the fox say ?
Sysout("chin chin chin tin tin tin");
}
}
3:提供动物级的噪声接口
4:只需在Fox类中提供您选择的NoiseInterface类型
这个设计的惊人之处在于,你永远不用担心它的实现。我会告诉你怎么做
你只要打电话就行了
现在,将来你想让狐狸静音。
您将创建一个新的界面
public class Mute implements NoiseInterface {
@Override
public void speak()
{
Sysout("No sound");
}
}
只需更改Fox类构造函数中的NoiseBehavior
noiseMaker = new Mute();
你可以找到更多关于开闭原则的信息。@T.J.Crowder编辑了我的答案。除非Turtle
也被认为是一个抽象类,否则它不能有任何抽象方法。拥有public abstract void makeNoise()
insideTurtle
意味着您也需要设置类abstract
。因此,您不能实例化海龟。这似乎不正确……这取决于你想要实现什么。您还可以选择,默认情况下,Animal
没有此方法,它通过附加的接口CanMakeNoise
。或者您有一个空的实现,就像您当前拥有的一样,或者您抛出UnsupportedOperationException
,这意味着Turtle
不能发出任何噪音。如果将其抽象化,则意味着您希望Turtle
发出噪音,但是从Turtle
扩展的类需要实现它,因为您没有提供默认实现。因此,问题是谁扩展了Turtle?如果你把它放在抽象的位置,那么如何实例化它呢?这是海龟们一直在思考的一个好问题,makeNoise
在错误的地方。我认为提供makeNoise
的东西应该是一个接口(也许NoiseMaker
)。是的,我已经把它变成了一个接口interface@Johny谢谢也许我会使用接口,因为这是所有动物都不常见的行为subclasses@AxelH为你修正了这显然是一个糟糕的设计,需要修正(除非这太晚了…)
public class Fox extends Animal
{
public Fox()
{
noiseMaker = new FoxSound();
}
public void makeNoise()
{
noiseMaker.speak();
}
}
Animal me = new Fox();
fox.makeNoise();
public class Mute implements NoiseInterface {
@Override
public void speak()
{
Sysout("No sound");
}
}
noiseMaker = new Mute();