【问题标题】:java: inheritance questions about overriding methodsjava:关于覆盖方法的继承问题
【发布时间】:2023-03-07 09:52:01
【问题描述】:

如果父类中的方法不需要参数,但子类中的覆盖方法需要一个。在父类的方法中使用无用参数是一种好习惯吗?

//in parent class:
getFeature(String name){
    return defaultFeature;
}

//in child class:
getFeature(String name){
    return new Feature(name);
}

该方法在父类中的另一个方法中使用且仅使用。所以我们对父类和子类有相同的签名。真正的问题是两个子类的 getFeature 实现略有不同。

或者有没有更好的方法来实现这一点?

【问题讨论】:

  • 如果你这样做,它就不再是覆盖,而是重载。
  • @LuiggiMendoza:不是真的,相对于问题的最后一句话。
  • 这在我看来是抽象工厂模式,除了父类不是抽象的并且返回一些默认对象。反正不同签名的方法(名称+参数列表)是不同的方法,所以不能在父类中有method getName(),在子类中有方法getName(String name),希望重写。它们没有相同的签名。
  • 但是这个getFeature是用的,而且只用在父类的另一个方法中。这就是多态性发生的地方。
  • 从您上次的评论来看,这似乎是一种可能的代码异味。你能进一步解释一下父类的设计吗?这个name 参数总是需要吗?

标签: java class inheritance overriding


【解决方案1】:

在父类的方法中有一个无用的参数是个好习惯吗?

这取决于。如果 API 设计预期子类将需要参数,即使基类不需要,并且您希望确保可以通过父类型引用调用方法的参数版本:

Parent instance = new Subclass();
Feature f = instance.getFeature("foo");

...那么您必须在父类签名中包含该参数,即使您没有在实现中使用它。您可能也拥有始终提供非参数功能的无参数版本:

class Parent {
    public Feature getFeature() { // Maybe you'd want this, maybe not
        return defaultFeature;
    }
    public Feature getFeature(String name) {
        return this.getFeature();
    }
}
class Subclass extends Parent {
    @Override
    public Feature getFeature(String name) {
        return /*...*/;
    }
}

但如果您预计子类实例将仅与子类类型的引用一起使用:

Subclass instance = new Subclass();
// ^^---------- note
Feature f = instance.getFeature("foo");

...那么父类的getFeature 没有理由拥有它。子类可以将其添加为重载:

class Parent {
    public Feature getFeature() {
        return defaultFeature;
    }
}
class Subclass extends Parent {
    public Feature getFeature(String name) {
        return /*...*/;
    }
}

这只是意味着Parent 类型的引用将仅限于getFeature 的无参数功能。

【讨论】:

  • 在第一种方法中,问题(或缺点)是在子类对象中仍然可以访问无参数方法。在这些情况下,我们总是需要做出一些权衡。
【解决方案2】:

您实际覆盖,这是一种误导性的方法,因为类的客户端必须传递 String,而这仅在子类中使用:

child.getFeature("makeSenseArg");
parent.getFeature("notUsedArg");

您应该在子类中重载getFeature() 方法:

//in parent class:
getFeature(){
    return defaultFeature;
}

//in child class:
getFeature(String name){
    return new Feature(name);
}

您不会再从多态性中受益,但这可能不是问题,因为这是两种不同的行为。
将它们合并到一个方法签名中可能不是最好的做法。


请注意,如果您确实需要依赖覆盖,可以使用 @javax.annotation.Nullable 注释参数。
它使类客户端的 API 更清晰,此外,Sonar 等代码分析工具也将这些注释考虑在内。
这会给:

// parent class
Feature getFeature(@Nullable String name){
    return defaultFeature;
}

此外,如果对于被覆盖的方法,参数是强制性的,你甚至可以指定“反向”注解(@javax.validation.constraints.NotNulll):

//child class
Feature getFeature(@NotNulll String name){
    return new Feature(name);
}

客户会打电话给他们:

child.getFeature("makeSenseArg");
parent.getFeature(null);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-16
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    相关资源
    最近更新 更多