java - protegidas - ¿Cómo forzar a la clase derivada a llamar al supermétodo?(Como Android lo hace)
herencia en java ejemplos (8)
Aquí está la fuente de Activity#onCreate()
: se trata de casi todos los comentarios ( original - vea la línea ~ 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;
}
así que supongo que el complemento ADT Eclipse es lo que agrega automáticamente esa llamada a super.onCreate()
por usted. Sin embargo, es una suposición total.
Me preguntaba, cuando creaba nuevas clases de Activity
y luego onCreate()
método onCreate()
, en eclipse siempre obtengo automáticamente: super.onCreate()
. ¿Como sucedió esto? ¿Existe una palabra clave java en el resumen o clase principal que lo fuerza?
No sé si es ilegal no llamar a la súper clase, pero recuerdo que en algunos métodos recibí una excepción por no hacer esto. ¿Esto también está incorporado en Java? ¿Puedes usar alguna palabra clave para hacer eso? ¿O cómo se hace?
Eclipse solo está ayudando, recordándole que puede llamar a la implementación de la superclase si lo desea.
probablemente esté recibiendo un error porque no está haciendo algo necesario que hace la superclase, ya que no está llamando a su implementación.
Eclipse solo te ayuda a hacer las cosas bien y evitar excepciones.
Desde http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle )
Las clases derivadas deben llamar a la implementación de este método de la superclase. Si no lo hacen, se lanzará una excepción.
Esto se agrega en la biblioteca de anotación de soporte:
dependencies {
compile ''com.android.support:support-annotations:22.2.0''
}
http://tools.android.com/tech-docs/support-annotations
@CallSuper
No hay nada en Java que fuerce la invocación de super, y hay muchos ejemplos en los que no te gustaría. El único lugar donde puedes forzar la llamada de super es en constructores. Todos los constructores tienen que llamar a un constructor de superclase. Uno (el constructor sin argumentos) se insertará si no escribe uno explícitamente, y si no hay un constructor sin argumentos, debe llamarlo explícitamente.
Para responder a su pregunta real, la creación automática de la llamada a super.onCreate () es una característica del complemento ADT. En java, no se puede forzar directamente a una subclase para que invoque la súper implementación de un método, afaik (consulte el patrón descrito en otras respuestas para solucionar problemas). Sin embargo, ten en cuenta que en Android no estás instanciando objetos de actividad (u objetos de servicio) directamente: pasas una intención al sistema y el sistema crea una instancia del objeto y llama a Crear () sobre él (junto con otros métodos de ciclo de vida). Entonces, el sistema tiene una referencia de objeto directo a la instancia de la Actividad y es capaz de verificar (presumiblemente) algún Booleano que se establece en verdadero en la implementación de la superclase de onCreate (). Aunque no sé exactamente cómo se implementa, probablemente se parece a esto:
class Activity
{
onCreate()
{
superCalled = true;
...
}
...
}
Y en la clase de nivel "sistema" que recibe el Intento y crea una instancia del objeto Activity desde él:
...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
Exception e = new Exception(...) //create an exception with appropriate details
throw e;
}
Supongo que probablemente sea un poco más complejo que eso, pero entiendes la idea. Eclipse crea automáticamente la llamada porque el complemento ADT se lo dice, para su comodidad. Feliz codificación!
Si quiere obligar a las subclases a ejecutar la lógica de la clase padre, un patrón común es algo como lo siguiente:
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";
}
}
En realidad, esto no responde a su pregunta acerca de qué hace que Eclipse inserte automáticamente una llamada de superclase en la implementación; pero no creo que ese sea el camino a seguir, ya que esto siempre se puede eliminar.
En realidad, no se puede hacer cumplir que un método debe llamar a la versión de la superclase con una palabra clave Java, o algo por el estilo. Sospecho que tus excepciones simplemente provienen de algún código en la clase padre que verifica invariantes esperados, o algo, que fueron invalidados por tu enfoque. Tenga en cuenta que esto es sutilmente diferente de lanzar una excepción porque no pudo llamar a super.onCreate()
.
Si quiere asegurarse de que también se llama al método de la superclase, debe engañar un poco: no permita que se sobrescriba el método de superclase, pero haga que llame a un método protegido invalidable.
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();
}
}
De esta forma, el usuario debe llamar a Super.foo () o Base.foo () y siempre será la versión de clase base, ya que se declaró como final. El material específico de la implementación se encuentra en impl_stuff (), que puede anularse.