提醒开发人员在Java中调用`super.foo()`。

7
假设我有这两个类,其中一个继承另一个:
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 这就是我想要的方式:
但是有了上述内容仍然很好,甚至可以提供一个自定义消息来执行其他操作,例如:“无法覆盖Bar中的最终方法,请改为从您的实现方法中调用它”

1
这可能可以通过静态代码分析工具/规则检查器(例如IDEA)实现。它很可能不应该在运行时(例如使用反射)完成。 - user2864740
1
如果您无法使用模板模式,FindBugs有一个注释可以检测缺失的覆盖:OverrideMustInvoke - JB Nizet
我甚至会很高兴让这个方法“不可重写”:这就是final的作用。 - JB Nizet
我认为这样做是设计不良的问题。通常,如果需要这样的操作,可以通过Javadoc来处理。如果你希望用户调用db.close()方法,只需在完成与db的工作后让他单独调用即可。 - svz
2个回答

4

编辑:回答经过编辑的问题,包括:

我甚至会很高兴使这个方法“无法覆盖”

…只需将方法设置为final。这将防止子类覆盖它。来自JLS第8.4.3.3节

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

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

为了回答原始问题,考虑使用模板方法模式

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”确实可以做到... - Jon Skeet
抱歉,请查看第二次编辑,原始内容仍然是问题的一部分。 - FabianCook

0
你可以做的是像下面这样的东西。
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”,以便子类无法覆盖并避免执行强制性操作


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接