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

问题描述 投票:0回答:7

我有一个在广泛的层次结构中使用和重写的 init 方法。然而,每个 init 调用都扩展了前一个调用所做的工作。所以很自然地,我会:

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

自然地,这将确保所有内容都被调用和实例化。我想知道的是:我可以创建一种方法来确保调用 super 方法吗?如果所有的 init 都没有被调用,那么对象就会崩溃,所以如果有人忘记调用

super
,我想抛出异常或错误。

TYFT ~Aedon

java polymorphism super
7个回答
13
投票

而不是尝试这样做——顺便说一句,我认为这是不可能实现的! -- 换一种方法怎么样:

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!

这对你有用吗?


9
投票

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

public class Base {
    private boolean called;
    public Base() { // Doesn't have to be the c'tor; works elsewhere as well.
                    // In fact, shouldn't call overridable methods from c'tor.
        called = false;
        init();
        if (!called) {
            // throw an exception
        }
    }
    protected void init() {
        called = true;
        // other stuff
    }
}

2
投票

Android 实际上是在

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

例如,在

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


1
投票

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

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

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


0
投票

使继承树顶部的类在初始化时设置一个标志。然后继承树底部的类可以检查该标志以查看是否已遍历整个树。我会制作文档,说明

base
的每个子级都应包含以下初始化代码:

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

基地使用的地方

_baseIsInitialized = true;

相反,强迫你的孩子打电话

super.init()
需要深思熟虑,而且很可能包括丑陋的黑客行为。


0
投票

我不知道有什么方法可以用方法来做到这一点。

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

我注意到您正在编写一个 init 方法。您能否重构,以便您的代码使用构造函数而不是 init 方法?这会让你一开始就出现这种行为。无论如何,有些人(例如我)更喜欢构造函数而不是 init 方法,部分原因就是这个原因。

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


0
投票

现在您可以使用

@CallSuper
注释您的方法。这将检查该方法的任何重写是否调用 super()。这是一个例子:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.