Как заставить производный класс вызывать супер метод? (Как у Android)



мне было интересно, при создании новых Activity классы, а затем переопределение onCreate() метод, в eclipse я всегда получаю автоматическое добавление:super.onCreate(). Как это происходит? Есть ли ключевое слово java в абстрактном или родительском классе, которое заставляет это делать?



Я не знаю, является ли незаконным не вызывать суперкласс, но я помню, что в некоторых методах я получил исключение, брошенное за то, что не делал этого. Это также встроенный в java? Вы можете использовать некоторые ключевые слова, чтобы сделать это? Или как это готово?

502   8  

8 ответов:

вот источник 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 ключевое слово, или что-нибудь в этом роде. Я подозреваю, что ваши исключения просто пришли из какого-то кода в родительском классе, проверяя ожидаемые инварианты или что-то еще, что было признано недействительным вашим подходом. Обратите внимание, что это тонко отличается от бросания исключения , потому что вы не называете super.onCreate().

чтобы ответить на ваш фактический вопрос, автоматическое создание вызова super.onCreate () - это функция плагина ADT. В java вы не можете напрямую заставить подкласс вызывать супер-реализацию метода afaik (см. шаблон, описанный в других ответах для обхода). Однако имейте в виду, что в Android вы не создаете объекты Activity (или объекты Service) напрямую - вы передаете намерение системе, и система создает экземпляр объекта и вызывает onCreate() на нем (наряду с другими методами жизненного цикла). Таким образом, система имеет прямую ссылку на объект экземпляра Activity и может проверить (предположительно) некоторое булево значение true в реализации суперкласса onCreate(). Хотя я не знаю точно, как это реализовано, это, вероятно, выглядит примерно так:

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

и в классе уровня "система", который получает намерение и создает из него экземпляр объекта Activity:

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

Я предполагаю, что это, вероятно немного сложнее, но вы получите идею. Eclipse автоматически создает вызов, потому что плагин 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 () или база.foo () и это всегда будет версия базового класса, так как она была объявлена окончательной. Специфичный для реализации материал находится в impl_stuff (), который может быть переопределен.

в Java нет ничего, что заставляет вызывать super, и есть много примеров, когда вы этого не хотите. Единственное место, где вы можете принудительно вызвать super, - это конструкторы. Все конструкторы должны вызывать конструктор суперкласса. Один (конструктор без аргументов) будет вставлен, если вы не пишете его явно, и если нет конструктора без аргументов, то вы должны вызвать его явно.

Eclipse просто помогает, напоминая вам, что вы можете вызвать реализацию суперкласса, если хотите.

вы, вероятно, получаете ошибку, потому что вы не делаете что-то необходимое, что делает суперкласс, так как вы не вызываете его реализацию.

Eclipse просто помогает вам делать все правильно и избегать исключений.

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

производные классы должны вызывать реализацию суперкласса этого метода. Если они этого не сделают, будет выдано исключение.

Comments

    Ничего не найдено.