2010-04-13 20 views
28

¿Cuándo llamas a super() en Java? Lo veo en algunos constructores de la clase derivada, pero ¿no se llaman automáticamente los constructores para cada clase padre? ¿Por qué necesitarías usar super?Llamar a super()

Respuesta

44

Si proporciona una clase como esta:

public class Foo 
{ 
} 

o esto:

public class Foo() 
{ 
    public Foo() 
    { 
    } 
} 

el compilador generará código para esto:

public class Foo() 
{ 
    public Foo() 
    { 
     super(); 
    } 
} 

Por lo tanto, en sentido estricto, la la llamada a "super()" siempre está ahí.

En la práctica, solo debe llamar a "super (...)" donde hay parámetros que desea pasar al constructor padre.

No es incorrecto llamar "super()" (sin parámetros) pero la gente se reirá de ti :-)

+2

¿No debería 'Foo' ampliar otra clase? De lo contrario, la llamada a super no tiene sentido ... –

+4

Foo extiende implícitamente java.lang.Object. La llamada a super TIENE que estar ahí y por eso el compilador la pone. – TofuBeer

+1

@Camilo Diaz, la llamada a super es la llamada al constructor en java.lang.Object – Yishai

0

super() es implícita cuando no hay otra clase/constructor de la superclase se llama.

0

Puede llamar a super() con parámetros si desea llamar a un constructor no predeterminado de la superclase, o si la superclase no tiene un constructor predeterminado. El compilador solo puede insertar el constructor predeterminado, sin argumentos super().

2

No hay necesidad de llamar a super().

De Accessing Superclass Members:

Con super(), la superclase constructor sin argumentos se llama. Con super (lista de parámetros), se llama al constructor de superclase con una lista de parámetros correspondiente.

Nota: Si un constructor no invoca explícitamente un constructor de superclase, el compilador de Java inserta automáticamente una llamada al constructor sin argumentos de la superclase. Si la superclase no tiene un constructor sin argumentos, obtendrá un error en tiempo de compilación. Object tiene un constructor así, por lo que si Object es la única superclase, no hay problema.

+0

Gracias por la nota sobre la llamada automática del constructor de objetos. – Romain

0

Porque el constructor de la superclase no se llama automáticamente. Podría haber, por ejemplo, varios constructores, algunos de los cuales toman parámetros adicionales. Por lo que no siempre tienes un super "vacío"() declaración, pero algo como esto:

public class DerivedClass extends SomeOtherClass 
{ 
    private String anotherParameter; 
    public DerivedClass(int parameterA, String parameterB, String anotherParameter) 
    { 
    super(parameterA, parameterB); 
    this.anotherParameter = anotherParameter; 
    } 
} 

Editar:, obviamente, se me olvidó decir (o mi elección de palabras, simplemente no era bueno, pero No soy hablante nativo, lo siento por eso) que si la superclase no toma ningún parámetro, java/compilador hará la llamada a super(). (Ahora que volví a leer mi respuesta, puedo ver que realmente parece que siempre tendrías que llamar a super().)

+0

Dado el contexto del ejemplo que dio el "no llamado automáticamente" tiene sentido, pero sí podría haber sido redactado mejor (le di el +1 no el -1 seno Obtuve lo que estaba diciendo) – TofuBeer

23

Usted haría necesidad de utilizar super() en un caso como este:

public class Base { 
    public Base(int foo) { 
    } 
} 

public class Subclass extends Base { 
    public Subclass() { 
     super(15); 
    } 
} 

Este es un ejemplo muy artificial, pero la única vez que necesidad de llamar a super() es si estás heredando de una clase que no proporciona un constructor predeterminado sin parámetros. En este caso, debe llamar explícitamente al super() desde el constructor de su subclase, pasando los parámetros que necesite para satisfacer el constructor de la clase base. Además, la llamada al super() debe ser la primera línea del constructor de la clase heredada.

+0

Esa última frase es bonita importante. – hotshot309

1

Como se ha dicho, si su constructor no llama explícitamente a super() con o sin algún argumento, java llamará automáticamente al constructor predeterminado de la superclase.

Sin embargo, llamar explícitamente a super() es solo eso - explícito. Si sabe que el constructor de la superclase hace algo significativo, es un recordatorio útil para quien mantiene su código que se llama primero a super() (y puede tener efectos secundarios). Esto incluso podría ser un lugar útil para poner un punto de interrupción durante la depuración.

+0

Nunca había pensado en esto; cuando vi la llamada explícita a 'super' en el código de otras personas, simplemente pensé que estaban" esforzándose mucho "para asegurarse de que se usara el comportamiento especial de la superclase (y no se dieron cuenta de que sucedería de todos modos). Supongo que podría tomar su enfoque o argumentar que, tan pronto como vea que una clase se extiende a otra, debería mirar la clase de padres para ver qué comportamiento se define allí. – hotshot309

1

Cuando tienes una clase que amplía otra clase y la clase padre no tiene un constructor predeterminado, entonces debes usar super() en el constructor Son para llamar al constructor en la clase padre con los argumentos adecuados como este:

class A 
{ 
    int a; 
    A(int value) 
    { 
     this.a=value; 
     System.out.println("A Constructor " + a); 
    } 
} 

class B extends A 
{ 
    int b; 
    B() 
    { 
     super(5); 
     this.b=10; 
     System.out.println("B Constructor " + b); 
    } 

} 

tienes que saber que no puedes usar "super" con "this" si quieres llamar a otro constructor en el calss usando "this".

2

Si no puede llamar a super en un constructor, el compilador agregará una superllama sin argumento como el constructor padre para la primera línea del cuerpo del constructor.

Así como en el código previamente publicado

public class Foo 
{ 
} 

o

public class Foo 
{ 
    public Foo() 
    { 
    } 
} 

el compilador generará código que se alinea con las reglas de Java. Todos los objetos son subclases de java.lang.Object, por lo que el compilador compilará como si fue escrito

// All classes extend Object. This is Java, after all. 
public class Foo extends java.lang.Object 
{ 
    public Foo() 
    { 
    // When constructing Foo, we must call the Object() constructor or risk 
    // some parts of Foo being undefined, like getClass() or toString(). 
    super() 
    } 
} 

Pero si la superclase no tiene un constructor que coincide con los parámetros, a continuación, debe llamar al apropiado constructor de super clase no coincidente.

public class LightBlue extends java.awt.Color 
{ 
    public LightBlue() 
    { 
    // There is no Color() constructor, we must specify the suitable super class 
    // constructor. We chose Color(int red, int green, int blue). 
    super(172, 216, 230); 
    } 
} 

Otras veces, tal vez no es un constructor que coincide con la firma del constructor de la subclase, pero por alguna razón, usted no desean pasar los parámetros directamente al constructor de la superclase.

public class HSVColor extends Color 
{ 
    public HSVColor(int hue, int saturation, int value) 
    { 
    super(...code converting HSV to Red..., 
      ...code converting HSV to Green..., 
      ...code converting HSV to Blue); 
    } 
} 

Si usted se olvida de especificar explícitamente el super constructor de clase, el compilador añade en el no-arg super constructor de clase predeterminado. Sin embargo, si ese constructor no existe, entonces el compilador no compilará la clase, porque no está claro cuál de los constructores expuestos es el correcto para llamar.

Es una consideración de estilo, pero puede decidir incluir siempre la llamada a super(). Si elige hacerlo, será porque desea que el lector recuerde que los objetos de la clase base deben construirse como parte del objeto de la subclase, y que desea hacer que el constructor de la superclase particular sea explícito. Tradicionalmente, una llamada super() siempre incluida es bastante extraña, ya que tradicionalmente el código solo se escribe si difiere del comportamiento "predeterminado".

1

Quería proporcionar algo de información que no se ha mencionado hasta ahora. Si utiliza una llamada a this(...) en un constructor, entonces no se puede tener una llamada a super(...); Esto también incluye la inserción automática de Java de la llamada sin parámetros a super();

El siguiente ejemplo ilustra este punto, incluyendo comentarios explicativos:

public class B extends A { 
    private int x; 

    public B() { 
     // Java doesn't call super(); here, because 
     // of the call to this(...); below. 
     // You can't call super(...) here either, 
     // for the same reason. 

     this(42); // Calls public B(int x) below. 
    } 

    public B(int x) { 
     // Java does call super(); here. 
     // You can call super(...) here, if you want/need to. 
     // The net result of calling new B() above is that 
     // super(...) for class A only gets called once. 

     this.x = x; 
    } 
} 
0

Aunque super() no hace nada funcional para el compilador (el constructor predeterminado de la superclase se llama automáticamente), ciertamente me sirve mucho. Me dice: "No elimines el constructor vacío. Está ahí por una razón".

Un ejemplo perfecto es donde crea Spring managed beans o JPA Entities y ha creado un constructor con parámetros.

@Entity 
public class Portfolio { 

    ... 

    public Portfolio() { 
     super(); // This says to me: DON'T DELETE! 
    } 

    /** 
    * Because there is now a parameterised constructor (me), 
    * the default constructor no longer exists. This means 
    * that for this example, you need an empty constructor in place (above) 
    **/ 
    public Portfolio(String name) { 
     this.name = name; 
    } 
} 
0

Super se llama cuando queremos heredar algunos de los parámetros de la clase principal. No es obligatorio ya que el compilador siempre llama al constructor predeterminado. Si quieres heredar un constructor que tenga algunos parámetros, entonces debes llamar al súper. Entonces puedes usarlo

Cuestiones relacionadas