【问题标题】:Work around the need to override abstract methods in Java?解决在 Java 中重写抽象方法的需要?
【发布时间】:2014-12-14 08:05:58
【问题描述】:

我一直在处理一个涉及代表通用动物的抽象类的任务,该类具有猫、狗、爬行动物等的子类。超类具有每个子类实际上并未使用的抽象方法 . 例如,狗和猫使用了品种和性别的访问器和变异器,但爬行动物类不使用。我个人认为这是一个奇怪的设置,但这是作业所要求的。

起初我尝试省略在特定子类中未使用的抽象方法,但我很快发现这会导致错误,因为抽象方法没有被覆盖。我所要做的就是用适当的方法来解决这个问题......

public class Reptile extends Animal
...
public void setBreed(String newBreed){}  
public String getBreed(){return null;}  


...虽然看起来有点浪费,因为它们没有被使用。这不是一个大问题,但它让我好奇是否有替代方法可以替代给定子类中未使用的抽象方法。除此之外,当您需要覆盖抽象方法但实际上根本不使用该方法时,是否有任何约定?

【问题讨论】:

  • 为什么不为某些 getter 和 setter 提供默认实现?抽象类不需要所有方法都是抽象的。 (尽管这可能不适用于您的具体情况)
  • 根据您的使用情况,接口可能更合适。因为您能够实现多个接口来更好地定义您的类。虽然我不确定你的任务是否允许这样做。
  • 我不能有一个默认实现,因为分配特别要求我对导致我的帖子的方法使用抽象,尽管这样或接口会更合适。

标签: java inheritance overriding abstract


【解决方案1】:

这里有两个解决方案。

您可以有多个级别的抽象类。换句话说(这些是 shell 类和函数......即没有代码):

public abstract class Animal{
  public abstract void fooMethod();
}

public abstract class Pet extends Animal{
  public abstract void breed();
  public abstract void gender();
}

public class Reptile extends Animal{
  public void fooMethod(){}
}
public class Cat extends Pet{ //do the same for Dog
  public void fooMethod(){}
  public void breed(){}
  public void gender(){}
}

这样,Reptile 仍然扩展了 Animal,但是您知道 Reptile 没有品种或性别功能,因此您无需为它做任何事情。同样,Cat 和 Dog 也扩展了 Animal,但现在它们也必须覆盖品种和性别。

您的另一个解决方案是这样做(两个解决方案中最糟糕的一个):

public class Reptile extends Animal{
  public void breed(){
    throw new UnsupportedOperationException("Don't call Reptile#breed!!");
  }
}

这个解决方案特别糟糕,因为如果你没有适当的错误处理,这个异常会一直向上传播到你的 main 方法,如果没有对此的异常处理一直到你的 main 方法方法,那么你的程序就会崩溃。

我个人推荐选择 A。

【讨论】:

  • 很好的例子。另一种选择是使用接口。
  • 在我的特定示例中,是的,您可以使用接口。但是如果他在Animal中有一些功能(比如fooMethod不是抽象的),那么他显然不能。
  • 好点。幸运的是,在大多数情况下,您可以选择重组代码以允许使用接口。尤其是在 Java8 中添加了出色的 default 实现
  • 感谢您的快速回答-我认为可能有一些方法可以操纵异常处理,但我同意这不是最好的主意。此外,在这种情况下,我不想要更多的抽象层,尽管我很欣赏它如何工作的解释。您是否知道使用未使用的覆盖方法的任何约定,因为看起来这就是我将在我的作业中做的事情? (除非我的教授回复我并给我一些回旋余地!)
  • 我想第三种选择就是有一个空函数。就像“public voidbreed(){}”一样,它不会做任何事情。多层次的抽象类并不是一件坏事。在这里看起来可能有点矫枉过正,但在更大的代码库中,它会让你的代码更易于管理。此外,这样做更干净,并且是 Java 社区中普遍接受的处理方式。在你还在学习和养成习惯的时候养成这样做的习惯是个好主意;现在就在你还可以的时候养成正确的习惯,而不是养成坏习惯。
【解决方案2】:

@earchengine 的另一个版本的回答,添加了几个接口:

public abstract class Animal{
  public abstract void fooMethod();
}

public class Breed {...}
public interface Bred {
  Breed breed();
}

enum Gender { ...}

public interface Gendered
  Gender gender();
}

public class Reptile extends Animal {
  public void fooMethod(){}
}

public class Cat extends Animal implements Gendered, Bred {
  public void fooMethod(){}
  public Breed breed(){}
  public Gender gender(){}
}

public class Dog extends Animal implements Gendered, Bred {
  public void fooMethod(){}
  public Breed breed(){}
  public Gender gender(){}
}

【讨论】:

    猜你喜欢
    • 2013-01-02
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2021-03-13
    • 1970-01-01
    • 2014-03-19
    • 2014-05-30
    相关资源
    最近更新 更多