繁体   English   中英

覆盖非抽象方法是一种好习惯吗?

[英]Is it good practice to override non abstract methods?

我有一种情况,我需要修改超类方法以获得子类特定的逻辑,但方法逻辑对于所有其他子类是相同的。

我有两个选择:

1)使方法抽象,除了我有关的子类之外,重复相同的代码。

2)覆盖我想要改变逻辑的有关子类中的非抽象方法。

在Java中覆盖非抽象方法是一种很好的做法吗? 什么是概念上b / w覆盖非抽象方法和抽象方法的区别。

在某种程度上,这是一种风格问题。

这是一种常见做法 - 但也有人告诉您任何方法都不应该有多个实现。 这些人声称继承层次结构中的多个实现会导致难以调试的代码 - 因为您必须非常小心地确定实际调用此类方法的哪个版本。

当这些方法被其他方法大量使用时,你可以很容易地忽略大局 - 突然之间,由于某些子类中的重写,所以很难预测某些代码正在做什么。

要理解的关键 :对于X类中的某些方法foo() ,“单个”@Override很好,并且是常见的良好实践。 但是在X的子类中再次覆盖相同的foo()会很快导致各种问题。

换句话说:应该仔细地重新实现非抽象方法。 如果它使您的代码更难理解,那么寻找其他解决方案。 比如:具有固定(最终)方法的基类 - 该方法调用其他抽象方法来完成其工作。 例:

public abstract class Base {
  public final int doSomething() {
    String tmp = foo();
    int result = bar(tmp);
    return result * result;
  }
  public abstract String foo();
  public abstract int bar(String str);

如上所述:在这里你可以看到实现是“固定的”,因为doSomething()是最终的 - 但是必须在每个子类中覆盖所需的“成分”。

在Java中覆盖非抽象方法是一种很好的做法吗?

是。 (但是,请确保,您没有违反Liskov Substitution Principle (参考SO现有帖子),它告诉Child类不应该破坏父类类型定义。例如,来自Animal类的walk ()方法覆盖应该执行(具有)走路,它不应该执行飞行或其他。)

我还建议通过SOLID原理来理解设计原理。

什么是概念上b / w覆盖非抽象方法和抽象方法的区别。

AFAIK没有区别。 但是,为了清楚起见,抽象方法不包含任何实现,并且必须覆盖非抽象方法可以覆盖的位置。

覆盖我想要改变逻辑的有关子类中的非抽象方法 - 是

例如:如果在Object类中考虑toString()和hashCode(),则两个方法都是非抽象方法,但主要建议在子类中覆盖这些方法。

因为如果我想执行我的逻辑而不是超类逻辑需要覆盖并使用它,建议在这种情况下覆盖。

只要您不违反Liskov Subsitution原则 ,覆盖非抽象方法就完全没问题,并且通常会被实践:

Liskov的原则对签名强加了一些标准要求

  • 子类型中方法参数的逆变。
  • 子类型中返回类型的协方差。
  • 子类的方法不应抛出新的异常,除非这些异常本身是超类型方法抛出的异常的子类型。

除了签名要求之外,子类型还必须满足许多行为条件。

  • 子类型不能强化前提条件。
  • 后置条件不能在子类型中被削弱。
  • 超类型的不变量必须保留在子类型中。
  • 历史约束(“历史规则”)。 对象被认为只能通过他们的方法(封装)进行修改。 因为子类型可能引入超类型中不存在的方法,所以引入这些方法可能允许子类型中的状态更改在超类型中是不允许的。 历史约束禁止这一点。

只要该方法在覆盖时仍然遵守合同,就不应该对新实现的作用产生混淆。 该方法的新实现仍应遵循与覆盖之前的实现相同的合同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM