PREGUNTA: Dado este fragmento de código, ¿cuál será su salida?
class Cantante { public static String cantar() { return "la"; } }
public class Tenor extends Cantante {
public static String cantar () { return "fa"; }
public static void main (String [] args ) {
Tenor t = new Tenor ();
Cantante s = new Tenor ();
System.out.println (t.cantar () + " " + s.cantar() );
}
}
RESPUESTA: Do, re, mi, fa, sol… qué simpática la pregunta. Qué derroche de imaginación y simpatía. Veamos el fondo del asunto. Primera cuestión:
El fichero lleva el nombre de la clase pública. La otra clase no es conocida fuera del fichero.
Al crear un Tenor no ocurre nada puesto que no hay constructor ni campos.
El método cantar de Tenor es estático: esto significa que es un método de clase y que se puede invocar tanto sobre un objeto como sobre el nombre de la clase. Idem para el método cantar de Cantante.
Aunque parece que hay una sobreescritura de métodos, en realidad no la hay: un método estático no es sobreescribible y no funciona la ligadura dinámica de métodos. Si el método de la superclase fuera estático y el de la subclase no, saltaría un error “overridden method is static”.
Al crear un Cantante s con tipo Tenor, el tipo estático es Cantante, y el dinámico Tenor. Al invocar el método cantar sobre t se nos devuelve fa, y al invocar cantar sobre s, dado que s dispone de un método estático de s nombre se ejecuta y devuelve la. Por tanto la salida es : fa-la