Как заставить производный класс вызвать супер метод? (Как и Android)
Мне было интересно, создавая новые классы Activity
, а затем переопределяя метод onCreate()
, в eclipse всегда добавляю auto: super.onCreate()
. Как это произошло? Есть ли ключевое слово java в абстрактном или родительском классе, что заставляет это?
Я не знаю, незаконно ли вызывать суперкласс, но я помню, в некоторых методах, что я получил исключение, за которое не делал этого. Является ли это также встроенным в java? Можете ли вы использовать какое-то ключевое слово для этого? Или как это сделать?
Ответы
Ответ 1
Здесь источник Activity#onCreate()
- это почти все комментарии (original - см. строку ~ 800):
/**
* Called when the activity is starting. This is where most initialization
* should go: calling {@link #setContentView(int)} to inflate the
* activity 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
Это добавляется в библиотеку аннотаций поддержки:
dependencies {
compile 'com.android.support:support-annotations:22.2.0'
}
http://tools.android.com/tech-docs/support-annotations
@CallSuper
Ответ 3
Если вы хотите заставить подклассы выполнять логику родительского класса, общий шаблон выглядит примерно так:
public abstract class SuperClass implements SomeInterface
{
// This is the implementation of the interface method
// Note it 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 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
Чтобы ответить на ваш реальный вопрос, автосоздание вызова super.onCreate() является функцией плагина ADT.
В java вы не можете напрямую заставить подкласс назвать супер-реализацию метода afaik (см. Шаблон, описанный в других ответах для обхода). Однако имейте в виду, что в Android вы не создаете объекты Activity (или объекты службы) напрямую - вы передаете Intent системе, и система создает экземпляр объекта и вызывает onCreate() на нем (наряду с другими методами жизненного цикла). Таким образом, система имеет непосредственную ссылку на объект экземпляра Activity и может проверить (предположительно) некоторый логический параметр, который установлен в true в реализации суперкласса onCreate().
Хотя я точно не знаю, как это реализовано, вероятно, это выглядит примерно так:
class Activity
{
onCreate()
{
superCalled = true;
...
}
...
}
И в классе уровня "system", который получает Intent и создает экземпляр объекта Activity из него:
...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
Exception e = new Exception(...) //create an exception with appropriate details
throw e;
}
Мое предположение, вероятно, немного сложнее, чем это, но вы получаете идею. Eclipse автоматически создает вызов, потому что плагин ADT сообщает об этом, как удобство. Счастливое кодирование!
Ответ 5
Если вы хотите абсолютно убедиться, что метод суперкласса также вызывается, вы должны немного обмануть: не разрешать перезаписывать суперкласс-метод, но он вызывает переопределяемый защищенный метод.
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(), которая может быть переопределена.
Ответ 6
В Java нет ничего, что принудительно вызывает супер, и есть много примеров, когда вы не захотите. Единственное место, где вы можете принудительно вызвать супер, - это конструкторы. Все конструкторы должны вызывать конструктор суперкласса. Один (конструктор без аргументов) будет вставлен, если вы не будете писать его явно, а если нет конструктора без аргументов, вы должны явно его вызывать.
Ответ 7
Eclipse просто полезен, напоминая вам, что вы можете назвать реализацию суперкласса, если хотите.
вы, вероятно, получаете сообщение об ошибке, потому что вы не делаете что-то необходимое для суперкласса, поскольку вы не вызываете его реализацию.
Ответ 8
Eclipse просто помогает вам делать все правильно и избегать исключений.
Из http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)
Производные классы должны переходить к реализации суперкласса этого метода. Если они этого не сделают, будет выбрано исключение.