如何强制对super方法进行多态调用?

时间:2011-05-26 17:15:38

标签: java polymorphism super

我有一个init方法,通过广泛的层次结构使用和覆盖。然而,每个init调用都扩展了之前的工作。很自然地,我会:

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

自然,这将确保所有内容都被调用和实例化。我想知道的是:我可以创建一种方法来确保调用超级方法吗?如果所有的init都没有调用,那么obejct就会出现故障,所以如果有人忘记调用super,我想抛出异常或错误。

TYFT~Aedon

7 个答案:

答案 0 :(得分:12)

而不是试图这样做 - 我不认为这是可以实现的! - 如何采用不同的方法:

abstract class Base {
 public final void baseFunction() {
   ...
   overridenFunction(); //call the function in your base class
   ...
 }

 public abstract void overridenFunction();
}
...
class Child extends Base {
 public void overridenFunction() {...};
}

...
Base object = new Child();
object.baseFunction(); //this now calls your base class function and the overridenFunction in the child class!

这会对你有用吗?

答案 1 :(得分:8)

如果派生类无法调用超类,这是引发异常的一种方法:

public class Base {
    private boolean called;
    public Base() { // doesn't have to be the c'tor; works elsewhere as well
        called = false;
        init();
        if (!called) {
            // throw an exception
        }
    }
    protected void init() {
        called = true;
        // other stuff
    }
}

答案 2 :(得分:2)

Android实际上在Activity课程中实现了这一点。我不确定他们是如何或是否必须为运行时构建支持,但我会查看Activity类实现的开源代码。具体来说,在任何生命周期方法中,您必须在执行任何操作之前调用相应的超类方法,否则会抛出SuperNotCalledException

例如,在onCreate()中,您要做的第一件事就是致电super.onCreate()

答案 3 :(得分:1)

我经常喜欢使用这个解决方案。它不会引发运行时错误,但会显示语法错误:

 @CallSuper
 public void init() {
     // do stuff
 }

这是Android支持注释的一部分。

答案 4 :(得分:0)

使继承树顶部的类在初始化时设置标志。然后,继承树底部的类可以检查该标志,以查看是否已遍历整个树。我会制作文档,base的每个孩子都应该包含以下初始化代码:

super.init()
if (!_baseIsInitialized) {
    // throw exception or do w/e you wish
}

其中base使用

_baseIsInitialized = true;

另一种方式,强迫你的孩子打电话给super.init()是一件非常艰难的事,而且很可能包括丑陋的黑客。

答案 5 :(得分:0)

我不知道用方法做任何事情。

但请注意,这正是构造函数的工作原理。每个构造函数必须直接或间接调用其超类的构造函数之一。这是静态保证。

我注意到你正在编写一个init方法。你能重构一下,以便你的代码使用构造函数而不是init方法吗?这样就可以在门外发挥这种作用。有些人(例如我)更喜欢构造函数来初始化方法,部分原因就是这个原因。

请注意,使用构造函数而不是init方法可能并不意味着在您当前正在查看的类上使用它们 - 可能存在重构,它将需要初始化的状态移动到可以使用适当构造函数的并行类层次结构中。 / p>

答案 6 :(得分:0)

现在您可以使用@CallSuper为您的方法添加注释。这将Lint检查该方法的任何覆盖都调用super()。这是一个例子:

@CallSuper
protected void onAfterAttached(Activity activity) {
    if (activity instanceof ActivityMain) {
        mainActivity = (ActivityMain) activity;
    }
}

在上面的示例中,后代类中覆盖onAfterAttached但不调用super的任何方法都会使Lint引发错误。