【问题标题】:Warn developer to call `super.foo()` in java警告开发人员在 java 中调用 `super.foo()`
【发布时间】:2013-10-12 05:45:01
【问题描述】:

假设我有这两个类,一个扩展另一个

public class Bar{

    public void foo(){

    }

}

public class FooBar extends Bar {

    @Override
    public void foo(){
        super.foo(); //<-- Line in question
    }

}

我想要做的是警告用户调用超类的方法foo,如果他们没有在覆盖方法中,这可能吗?

或者有没有办法知道,如果我将类类型传递给超类,使用反射,覆盖其超类方法的方法调用原始方法?

例如:

public abstract class Bar{

    public Bar(Class<? extends Bar> cls){
        Object instance = getInstance();
        if (!instance.getClass().equals(cls)) {
            throw new EntityException("The instance given does not match the class given.");
    }
        //Find the method here if it has been overriden then throw an exception
        //If the super method isn't being called in that method
    }

    public abstract Object getInstance();

    public void foo(){

    }

}

public class FooBar extends Bar {

    public FooBar(){
        super(FooBar.class);
    }

    @Override
    public Object getInstance(){
        return this;
    }

    @Override
    public void foo(){
        super.foo();
    }

}

也许我甚至可以在超级方法上添加一个注释,以便表明它需要被调用?


编辑

注意,需要调用foo方法的不是超类,而是有人调用子类的foo方法,例如数据库close方法

如果归根结底,我什至很乐意让该方法“不可覆盖”,但仍想给它一个自定义消息。


编辑 2

这在某种程度上是我想要的:

但拥有上述内容仍然很好,或者甚至给他们一个自定义消息来执行其他操作,例如Cannot override the final method from Bar, please call it from your implementation of the method instead

【问题讨论】:

  • 这可以通过静态代码分析工具/规则检查器(例如 IDEA)来实现。它可能不应该在运行时完成(例如使用反射)。
  • 如果不能使用模板模式,FindBugs 有一个注解可以检测到丢失的覆盖:OverrideMustInvoke
  • 我什至会很高兴将方法设为“不可覆盖”:这就是 final 的用途。
  • 我会说做这样的事情是一个糟糕的设计问题。通常,如果需要,这些事情是通过 Javadoc 处理的。如果您希望用户调用 db.close() 方法,只需在使用 db 完成后让他单独调用它即可。

标签: java reflection


【解决方案1】:

编辑:回答已编辑的问题,其中包括:

我什至会很高兴让该方法“不可覆盖”

...只需创建方法final。这将防止子类覆盖它。来自section 8.4.3.3 of the JLS

可以将方法声明为final 以防止子类覆盖或隐藏它。

尝试覆盖或隐藏final 方法是编译时错误。

要回答原始问题,请考虑改用template method pattern

public abstract class Bar {
    public foo() {
        // Do unconditional things...
        ...
        // Now subclass-specific things
        fooImpl();
    }

    protected void fooImpl();
}

public class FooBar extends Bar {
    @Override protected void fooImpl() {
        // ...
    }
} 

这不会强制 FooBar 的子类覆盖 fooImpl 并调用 super.fooImpl() 当然 - 但 FooBar 可以 通过再次应用相同的模式来做到这一点 - 使其自己fooImpl 实现最终,并引入了新的受保护抽象方法。

【讨论】:

  • @SmartLemon:是的,如果你完全改变要求,final 确实会这样做......
  • 抱歉,请查看第二次编辑,原文仍然是问题的一部分。
【解决方案2】:

你可以做的就是跟随

public class Bar{

    public final void foo(){
        //do mandatory stuff
        customizeFoo();
    }

    public void customizeFoo(){

    }

}

public class FooBar extends Bar {

    @Override
    public void customizeFoo(){
        //do custom suff
    }

}

foo 方法在超类中设置为“final”,这样子类就不能覆盖和避免做强制性的事情

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 2022-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多