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()
inside
Turtle
意味着您也需要设置类
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();