Autor Tema: Cómo sobreescribir métodos en Java y hacer uso de super reutilización CU00690B  (Leído 4041 veces)

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Buenas tardes, compañeros.

Aquí dejo una posible solución del ejercicio CU00690B del curso Java desde cero.

Citar
EJERCICIO

Responde a las siguientes preguntas:

Supongamos la superclase Vehiculo que representa a cualquier tipo de vehículo y la subclase Taxi que representa a un tipo de vehículo concreto.

c) Escribe el código de una clase Vehiculo con los atributos matricula (String) y numeroDeRuedas (int), constructor, métodos getters y setters y método toString() para mostrar la información de un vehículo.

Código de la clase "Vehiculo":

Código: [Seleccionar]
public class Vehiculo{
    private String matricula;
    private int numeroDeRuedas;
   
    public Vehiculo(String matricula, int numeroDeRuedas){
        this.matricula = matricula;
        this.numeroDeRuedas = numeroDeRuedas;
    }
   
    public void setMatricula(String matricula){
        this.matricula = matricula;
    }
   
    public void setNumeroDeRuedas(int numeroDeRuedas){
        this.numeroDeRuedas = numeroDeRuedas;
    }
   
    public String getMatricula(){return matricula;}
    public int getNumeroDeRuedas(){return numeroDeRuedas;}
   
    public String toString(){
        return "El vehículo dispone de: "+getNumeroDeRuedas()+" ruedas y tiene una matrícula: "+getMatricula();
    }
}

Citar
d) Escribe el código de una clase Taxi que herede de vehículo y que además de los atributos de Vehiculo lleve un atributo adicional nombreDelConductor (String) y numeroDePlazas (int), constructor, métodos getters y setters y método toString() para mostrar la información de un Taxi.

Código de la clase "Taxi":

Código: [Seleccionar]
public class Taxi extends Vehiculo{
    private String nombreDelConductor;
    private int numeroDePlazas;
   
    public Taxi(String matricula, int numeroDeRuedas, String nombreDelConductor, int numeroDePlazas){
        super(matricula, numeroDeRuedas);
        this.nombreDelConductor = nombreDelConductor;
        this.numeroDePlazas = numeroDePlazas;
    }
   
    public void setNombreDelConductor(String nombreDelConductor){
        this.nombreDelConductor = nombreDelConductor;
    }
   
    public void setNumeroDePlazas(int numeroDePlzas){
        this.numeroDePlazas = numeroDePlazas;
    }
   
    public String getNombreDelConductor(){return nombreDelConductor;}
    public int getNumeroDePlazas(){return numeroDePlazas;}
   
    public String toString(){
        return "El vehículo dispone de: "+getNumeroDeRuedas()+" ruedas, tiene una matrícula: "+getMatricula()+
        " y el conductor se llama: "+getNombreDelConductor()+". El taxi dispone de: "+getNumeroDePlazas()+" plazas.";
    }
}

Citar
a) ¿Un objeto de tipo estático declarado Taxi puede contener a un objeto Vehiculo en tiempo de ejecución?

Este código no funcina:

Código: [Seleccionar]
public class TestEnmascaramiento01{
    public static void main(String []Args){
        Vehiculo vehiculo1 = new Vehiculo("8379 DRT",4);
        Taxi taxi1 = new Taxi("2039 DWQ",9,"Jose",20);
        taxi1 = vehiculo1;
    }
}

Y este, en cambio, sí:

Código: [Seleccionar]
public class TestEnmascaramiento01{
    public static void main(String []Args){
        Vehiculo vehiculo1 = new Vehiculo("8379 DRT",4);
        Taxi taxi1 = new Taxi("2039 DWQ",9,"Jose",20);
        taxi1 = (Taxi) vehiculo1;
    }
}

La explicación de esto la encontramos en la entrega CU00689B y precisamente aquí:

Citar
2. Conversión hacia abajo

Se trataría de poner lo que está arriba abajo, por ejemplo poner un Profesor como ProfesorInterino. Esto no siempre es posible. El supertipo admite cualquier forma (es polimórfico) de los subtipos: si el supertipo almacena el subtipo al que queremos realizar la conversión, será posible usando lo que se denomina “Enmascaramiento de tipos” o “Hacer Casting” (cast significa “moldear”). Si el supertipo no almacena el subtipo al que queremos convertirlo, la operación no es posible y saltará un error. Ejemplo:

Profesor p1; //p1 es tipo Profesor. Admite ser Profesor, ProfesorTitular o ProfesorInterino.

ProfesorInterino p44 = new ProfesorInterino(); //p44 es ProfesorInterino.

p1 = p44; // Conversión hacia arriba: sin problema. Ahora p1 que es tipo profesor, almacena un profesor interino

p44 = p1 // ERROR en la conversión hacia abajo. El compilador no llega tan lejos como para saber si p1 almacena un profesor interino u otro tipo de profesor y ante la incertidumbre salta un error. La forma de forzar al compilador a que “comprenda” que p1 está almacenando un profesor interino y por tanto puede asignarse a una variable que apunta a un profesor interino se llama “hacer casting”. Escribiríamos lo siguiente: p44 = (ProfesorInterino) p1;

Citar
b) ¿Un objeto de tipo estático declarado Vehiculo puede contener a un objeto Taxi en tiempo de ejecución?

Código: [Seleccionar]
public class TestEnmascaramiento02{
    public static void main(String []Args){
        Vehiculo vehiculo1 = new Vehiculo("8379 DRT",4);
        Taxi taxi1 = new Taxi("2039 DWQ",9,"Jose",20);
        vehiculo1 = taxi1;
    }
}

Vemos que el código compila.

Citar
1. Conversión hacia arriba

Se trataría por ejemplo de poner lo que está a un nivel inferior en un nivel superior, por ejemplo poner un profesor interino como profesor. Posible código: profesor43 = profesorinterino67;

Ponemos lo que está abajo (el profesor interino) arriba (como profesor). Esto es posible, pero dado que lo que está abajo generalmente contiene más campos y métodos que lo que está arriba, perderemos parte de la información. Sobre el objeto profesor43 ya no podremos invocar los métodos propios de los profesores interinos.

Citar
e) Escribe el código de una clase test con el método main que cree un objeto cuyo tipo es Vehiculo, instanciado como Taxi. Establece valores para sus atributos y usa el método toString(). ¿Qué método toString() resulta de aplicación, el propio de la clase Vehiculo o el propio de la clase Taxi? ¿Por qué?

Código de la clase "Test":

Código: [Seleccionar]
public class Test{
    public static void main(String []Args){
        Vehiculo vehiculo = new Taxi("4389 BTN",4,"Juan",8);
        System.out.println(vehiculo.toString());
    }
}

La respuesta a la pregunta "e" la encontramos al final de la entrega CU00690B y precisamente aquí:

Citar
el compilador se basa en el tipo estático para su trabajo, podríamos pensar que si invocamos a un objeto de tipo estático “superclase” y tipo dinámico “subclase” con un método sobreescrito, el método que se utilice sería el propio de la superclase. Pero sin embargo, esto no es así: el control de tipos del compilador se basa en los tipos estáticos pero en tiempo de ejecución los métodos que se ejecutan dan preferencia al tipo dinámico. Es decir, en tiempo de ejecución Java está constantemente “buscando” (“ligando” o “despachando”) el método que corresponda en función del tipo dinámico al que apunta una variable.

Ampliación de la información:

Citar
Si el método invocado no se encuentra definido en el tipo dinámico de que se trate, Java busca el método en la superclase para tratar de ejecutarlo. Si no lo encuentra en la superclase, continúa subiendo niveles de clase hasta alcanzar a la clase Object. Si en la clase Object tampoco se encontrara un método con ese nombre, el programa no llegaría a compilar. Decimos que los métodos en Java son polimórficos porque una misma llamada en un programa puede dar lugar a la ejecución de distintos métodos según el tipo dinámico de una variable.

Gracias.
« Última modificación: 17 de Marzo 2016, 15:03 por Mario R. Rancel »

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Buenas tardes,

a) b) c) e) bien

En el apartado d) tienes que mejorar una cosa: en el método toString() debes reutilizar el código de la superclase en lugar de repetir. Ver este hilo como ejemplo https://www.aprenderaprogramar.com/foros/index.php?topic=1147.0

Saludos

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Graicas, Mario.

Corrección del código de la clase "Taxi":

Código: [Seleccionar]
public class Taxi extends Vehiculo{
    private String nombreDelConductor;
    private int numeroDePlazas;
   
    public Taxi(String matricula, int numeroDeRuedas, String nombreDelConductor, int numeroDePlazas){
        super(matricula, numeroDeRuedas);
        this.nombreDelConductor = nombreDelConductor;
        this.numeroDePlazas = numeroDePlazas;
    }
   
    public void setNombreDelConductor(String nombreDelConductor){
        this.nombreDelConductor = nombreDelConductor;
    }
   
    public void setNumeroDePlazas(int numeroDePlzas){
        this.numeroDePlazas = numeroDePlazas;
    }
   
    public String getNombreDelConductor(){return nombreDelConductor;}
    public int getNumeroDePlazas(){return numeroDePlazas;}
   
    public String toString(){
        return super.toString()+". El nombre del conductor es: "+getNombreDelConductor()+". El taxi dispone de: "+getNumeroDePlazas()+" plazas.";
    }
}

Saludos.

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Ahora bien, estás reutilizando el código de la superclase  :D

Saludos

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".