如何强制派生类调用超级方法? (就像Android一样)
我想知道,当创build新的Activity
类,然后重写onCreate()
方法,在eclipse中,我总是得到自动添加: super.onCreate()
。 这是怎么发生的? 在强制这个抽象或父类有一个Java关键字?
我不知道是不是非法不要调用超类,但我记得在某些方法中,我得到了一个exception,因为没有这样做。 这也是内置到Java? 你可以使用一些关键字来做到这一点? 或者它是如何完成的?
这里是Activity#onCreate()
的来源 – 几乎所有的评论( 原始 – 见行〜800 ):
/** * Called when the activity is starting. This is where most initialization * should go: calling {@link #setContentView(int)} to inflate the * activity's UI, using {@link #findViewById} to programmatically interact * with widgets in the UI, calling * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve * cursors for data being displayed, etc. * * <p>You can call {@link #finish} from within this function, in * which case onDestroy() will be immediately called without any of the rest * of the activity lifecycle ({@link #onStart}, {@link #onResume}, * {@link #onPause}, etc) executing. * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> * * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b> * * @see #onStart * @see #onSaveInstanceState * @see #onRestoreInstanceState * @see #onPostCreate */ protected void onCreate(Bundle savedInstanceState) { mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, false); mCalled = true; }
所以,我的猜测是ADT Eclipse插件是自动为您添加对super.onCreate()
调用。 虽然这是一个总的猜测。
这被添加到支持注释库中:
dependencies { compile 'com.android.support:support-annotations:22.2.0' }
http://tools.android.com/tech-docs/support-annotations
@CallSuper
如果你想强制子类来执行父类的逻辑,一个常见的模式是类似于以下内容:
public abstract class SuperClass implements SomeInterface { // This is the implementation of the interface method // Note it's final so it can't be overridden public final Object onCreate() { // Hence any logic right here always gets run // INSERT LOGIC return doOnCreate(); // If you wanted you could instead create a reference to the // object returned from the subclass, and then do some // post-processing logic here } protected abstract Object doOnCreate(); } public class Concrete extends SuperClass { @Override protected Object doOnCreate() { // Here's where the concrete class gets to actually do // its onCreate() logic, but it can't stop the parent // class' bit from running first return "Hi"; } }
这实际上并没有回答你提出什么提示Eclipse自动将超类调用插入到实现中的问题; 但是我不认为这是可以随时删除的方式。
你实际上不能强制一个方法必须用Java关键字或类似的东西来调用超类的版本。 我怀疑你的exception只是来自父类中的一些代码,检查预期的不variables,或者是你的方法无效的东西。 请注意,这与抛出exception有细微的区别, 因为你没有调用super.onCreate()
。
为了回答你的实际问题,自动创build对super.onCreate()的调用是ADT插件的一个特性。 在java中,不能直接强制子类调用方法afaik的超级实现(请参阅其他答案中描述的模式)。 但是,请记住,在Android中,您并不是直接实例化Activity对象(或者Service对象),而是将一个Intent传递给系统,然后系统实例化该对象并在其上调用onCreate()(以及其他生命周期方法)。 所以系统有一个对Activity实例的直接对象引用,并且能够在onCreate()的超类实现中检查(假定)一些布尔值设置为true。 虽然我不知道它是如何实现的,但它可能看起来像这样:
class Activity { onCreate() { superCalled = true; ... } ... }
并且在接收Intent的“系统”级别类中实例化Activity对象:
... SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass(); someActivitySubclassObject.onCreate(); if (!someActivityObject.isSuperCalled()) { Exception e = new Exception(...) //create an exception with appropriate details throw e; }
我的猜测可能是稍微复杂一点,但是你明白了。 Eclipse自动创build呼叫,因为ADT插件告诉它,作为一个方便。 快乐的编码!
如果你想确保超类方法被调用,你必须欺骗一下:不要让超类方法被覆盖,而是让它调用一个可重写的受保护的方法。
class Super { public final void foo() { foo_stuff(); impl_stuff(); } protected void impl_stuff() { some_stuff_that_you_can_override(); } } class Base extends Super { protected void impl_stuff() { my_own_idea_of_impl(); } }
这样,用户必须调用Super.foo()或Base.foo(),并且它将始终是最终声明的基类。 特定于实现的东西在impl_stuff()中,可以被重写。
Java中没有任何东西强制超级调用,有很多例子是你不想要的。 你可以强制调用超级的唯一的地方是在构造函数。 所有的构造函数都必须调用一个超类的构造函数。 如果你没有明确地写一个(no参数的构造函数),如果没有没有参数的构造函数,那么你必须明确地调用它。
Eclipse只是有帮助,提醒你可以调用超类的实现,如果你想。
你可能会得到一个错误,因为你没有做超类所需要的事情,因为你没有调用它的实现。
Eclipse只是帮助你正确地做事,避免出现exception。
从http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle )
派生类必须调用超类的这个方法的实现。 如果他们不这样做,就会抛出exception。