如何强制派生类调用超级方法?(就像Android一样)

Pet*_*rdk 76 java android overriding super

我想知道,在创建新Activity类然后重写onCreate()方法时,在eclipse中我总是自动添加:super.onCreate().这是怎么发生的?抽象或父类中是否有一个强制执行此操作的java关键字?

我不知道调用超类是否违法,但我记得在某些方法中我因为没有这样做而抛出异常.这也是内置到java中的吗?你可以使用一些关键字来做到这一点吗?或者它是如何完成的?

run*_*r49 175

这是在支持注释库中添加的:

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}
Run Code Online (Sandbox Code Playgroud)

http://tools.android.com/tech-docs/support-annotations

@CallSuper

  • 完美的答案。这应该被接受 (4认同)
  • @RizwanSohaib它不会强迫你做任何事情.它会突出显示并告诉您需要调用它.要做更复杂的事情,您需要一个注释处理器或自己实现逻辑.取决于IDE,它应该阻止您构建. (3认同)

And*_*yle 80

如果要强制子类执行父类的逻辑,则常见模式如下所示:

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

这实际上并没有回答你关于是什么促使Eclipse自动将超类调用插入到实现中的问题; 但是我不认为这是最好的方式,因为这总是可以删除.

您实际上不能强制执行方法必须使用Java关键字或类似的东西调用超类的版本.我怀疑你的异常只是来自父类中的一些代码,它们检查你的方法无效的预期不变量或其他东西.请注意,这与抛出异常略有不同,因为您无法调用super.onCreate().


Mat*_*all 9

这里的来源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;
}
Run Code Online (Sandbox Code Playgroud)

所以,我的猜测是ADT Eclipse插件是为你自动添加的调用super.onCreate().但总的来说,这是一个猜测.

  • 我想`mCalled = true`也用于可能的异常。也许不在onCreate()中,但是当确实抛出这样的异常时,它将使用该简单模式。 (2认同)

Lag*_*aer 8

如果你想要完全确定也调用了超类方法,你必须欺骗一下:不要让超类方法被覆盖,而是让它调用一个可覆盖的受保护方法.

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,用户必须调用Super.foo()或Base.foo(),它将始终是基类版本,因为它被声明为final.特定于实现的东西在impl_stuff()中,可以覆盖它.


spe*_*ode 8

要回答您的实际问题,自动创建对super.onCreate()的调用是ADT插件的一项功能.在java中,你不能直接强制子类调用方法的超级实现,afaik(参见其他答案中描述的模式来解决).但是,请记住,在Android中,您不是直接实例化Activity对象(或Service对象) - 您将Intent传递给系统,系统实例化对象并在其上调用onCreate()(以及其他生命周期方法).因此系统具有对Activity实例的直接对象引用,并且能够检查(可能)在onCreate()的超类实现中设置为true的一些布尔值.虽然我不确切知道它是如何实现的,但它可能看起来像这样:

class Activity
{
  onCreate()
  {
    superCalled = true;
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

在接收Intent并从中实例化Activity对象的"system"级别类中:

...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
  Exception e = new Exception(...) //create an exception with appropriate details
  throw e;
}
Run Code Online (Sandbox Code Playgroud)

我的猜测是它可能稍微复杂一些,但你明白了.Eclipse会自动创建调用,因为ADT插件会告诉它,为方便起见.快乐的编码!