代码之家  ›  专栏  ›  技术社区  ›  Peterdk

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

  •  71
  • Peterdk  · 技术社区  · 14 年前

    我在想,在创造新的 Activity 类,然后重写 onCreate() 方法,在Eclipse中,我总是自动添加: super.onCreate() . 这是怎么发生的?在抽象或父类中是否有强制这个的Java关键字?

    我不知道不调用超级类是否非法,但我记得在某些方法中,我因为不这样做而引发了异常。这也内置到Java中吗?你能用关键字来做吗?或者怎么做?

    8 回复  |  直到 9 年前
        1
  •  9
  •   Matt Ball    14 年前

    这是 Activity#onCreate() -几乎所有的评论( original - see line ~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() 为你。不过,这完全是猜测。

        2
  •  164
  •   runor49    9 年前

    这将添加到支持注释库中:

    dependencies {
        compile 'com.android.support:support-annotations:22.2.0'
    }
    

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

    @Callsuper公司

        3
  •  77
  •   Andrzej Doyle    14 年前

    如果你想的话 子类要执行父类的逻辑,公共模式如下所示:

    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关键字或类似的方法调用超类版本。我怀疑您的异常仅仅来自父类中的一些代码,检查期望的不变量,或者其他一些被您的方法无效的东西。注意,这与引发异常有细微的不同。 因为 你打电话失败 super.onCreate() .

        4
  •  8
  •   cadolphs    14 年前

    如果您希望确保绝对地也调用了超类方法,那么您必须有一点技巧:不允许覆盖超类方法,但是让它调用可重写的受保护方法。

    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(),并且在声明为final时,它始终是基类版本。特定于实现的东西在impl_-stuff()中,它可以被重写。

        5
  •  8
  •   speakingcode    12 年前

    要回答实际问题,自动创建对super.oncreate()的调用是ADT插件的一个特性。 在爪哇中,不能直接强制子类调用方法的超级实现,AFAIK(参见围绕其他工作所描述的模式)。但是,请记住,在Android中,您不是直接实例化活动对象(或服务对象)-您将意图传递给系统,系统实例化该对象并对其调用onCreate()(以及其他生命周期方法)。因此,系统有一个对活动实例的直接对象引用,并且能够(大概)检查在onCreate()的超类实现中设置为true的一些布尔值。 虽然我不知道它是如何实现的,但它可能看起来像这样:

    class Activity
    {
      onCreate()
      {
        superCalled = true;
        ...
      }
      ...
    }
    

    在接收意图并从中实例化活动对象的“系统”级类中:

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

    我想可能比那要复杂一点,但你明白了。Eclipse自动创建调用,因为ADT插件告诉它,这是一种方便。编码愉快!

        6
  •  4
  •   DJClayworth    14 年前

    Java中没有任何东西可以调用超级,而且当你不想调用时,有很多例子。唯一可以强制调用super的地方是构造函数。所有构造函数都必须调用超类构造函数。如果不显式编写,将插入一个(无参数构造函数),如果没有参数构造函数,则必须显式调用它。

        7
  •  3
  •   hvgotcodes    14 年前

    Eclipse只是提供帮助,提醒您可以根据需要调用超类实现。

    您可能会得到一个错误,因为您没有做超类所做的必要的事情,因为您没有调用它的实现。

        8
  •  1
  •   Flygenring    13 年前

    Eclipse只会帮助您正确地做事情并避免出现异常。

    http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle )

    派生类必须调用该方法的超级类的实现。如果不这样做,将引发异常。