Расположение вызовов super() в сгенерированном плагином Android Eclipse коде надежно?

Во многих методах Android, особенно в конструкторах и переопределенных методах, вы должны или даже должны вызывать метод родительского класса с помощью super(). Когда вы используете Eclipse Source > Override/Implement Methods..., вы получаете код из шаблона с такими тегами TODO:

public MyCanvas(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}


@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub      
    super.onDraw(canvas);
} 

Я не совсем понимаю, что делает суперкласс в каждом случае, поэтому я всегда вставляю свой код в точное место тегов //TODO. В этом примере я бы вызвал super() перед своим кодом в конструкторе и после моего кода в onDraw().

Могу ли я всегда полагаться на эти места вставки кода в сгенерированном коде? Есть ли простое правило/объяснение, когда вызывать super()?


person rgr_mt    schedule 14.02.2011    source источник
comment
Пока думаю на вопрос ответил - спасибо - результат мне не нравится. Размышляя о дизайне API и разделении ответственности, я считаю, что программисту приложений не нужно заглядывать в исходный код API, чтобы узнать, что происходит. Я хотел бы знать, если и когда вызывать super(), глядя на документацию API. Возможно, следует приложить усилия, чтобы точно задокументировать, что делает каждый из этих методов в классе API. Например, если View.onDraw() ничего не делает, я бы предпочел оставить его из соображений производительности, но я не уверен, что при этом что-то взорву.   -  person rgr_mt    schedule 15.02.2011
comment
При наличии надлежащей документации вам никогда не придется просматривать исходный код, чтобы выяснить, следует ли (и когда) вызывать super(). К сожалению, многие методы Android API плохо документированы (или вообще не документированы). И кроме того, большинство из нас давно усвоили: единственная хорошая документация — это сам код. По крайней мере, код доступен для Android (в отличие от некоторых других API, которые я не буду упоминать).   -  person Ted Hopp    schedule 15.02.2011
comment
Суперкласс должен вызываться ПЕРВЫМ в onRestoreInstanceState، onStop, onRestart, onStart, суперкласс должен вызываться ПОСЛЕДНИМ в onDestroy, onPause, onSaveInstanceState, onResume   -  person Yousha Aleayoub    schedule 04.09.2016


Ответы (3)


Это хороший вопрос. К сожалению, для этого нет простого правила. Вам нужно знать, что делает реализация суперкласса. Иногда (как в View.onDraw()) реализация суперкласса ничего не делает; вызов super() безвреден и не нужен. В других случаях (таких как Activity.onCreate()) реализация суперкласса выполняет критические операции, которые должны быть выполнены в какой-то момент обработки подкласса. Иногда то, что происходит, когда вы вызываете super(), должно происходить до любой обработки в подклассе, иногда в других точках. Иногда вы хотите полностью заменить обработку суперкласса своей собственной, и в этом случае вы вообще не вызываете super(). У вас есть полная свобода вызова версии суперкласса в любой точке (или даже в нескольких точках) логики вашего подкласса.

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

Если в документации недостаточно информации, вам нужно посмотреть исходный код. Код Android доступен здесь (релиз Gingerbread). Код API находится под core.

ИЗМЕНИТЬ Код больше недоступен на git.kernel.org. Вот два других места, где вы можете просмотреть код:

Основной код находится в репозитории Platform > Frameworks > Base

person Ted Hopp    schedule 14.02.2011

Могу ли я всегда полагаться на эти места вставки кода в сгенерированном коде?

Нет, иногда вы не хотите вызывать функцию super.method. Иногда вы хотите вызвать его первым, иногда последним и т. д. Это зависит от обстоятельств. Но я говорю о методах, а не о конструкторах.

Есть ли простое правило/объяснение, когда вызывать super()?

Вы всегда будете иметь все super как предыдущие пункты ответа. Единственный случай, когда вы не вызываете super, — это когда конструктор суперкласса не имеет параметров; в этом случае компилятор поставит super за вас.

Я не совсем понимаю, что делает суперкласс в каждом случае, поэтому я всегда вставляю свой код в точное место тегов //TODO.

Если вы сомневаетесь (я говорю о суперметодах), вы всегда можете взглянуть на исходный код. Google Code Search — хороший ресурс для этого. Затем вы можете решить, поместить ли свой код до или после метода super; или даже, не ставьте суперметод вообще.

Имейте в виду, что не помещать суперметод допустимо во время компиляции. Но некоторые методы на Android не будут работать, если вы не вызовете суперметод (например, метод onResume класса Activity).

Кроме того, иногда вы решаете, запускать суперметод или нет во время выполнения. Рассмотрим этот классический пример:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if( KeyEvent.KEYCODE_BACK == event.getKeyCode() ){
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

Если пользователь нажал клавишу «Назад», вы не вызовете метод super. Если пользователь этого не сделал, вы делегируете работу суперметоду.

person Cristian    schedule 14.02.2011