RSS

Orientación a objetos (IV) – Conversiones de tipos

12 May

Operador instanceof

Como hemos visto, es posible utilizar objetos mediante referencias a sus superclases. Por lo tanto, a veces es necesario saber con qué objetos reales estamos tratando. Para ello tenemos el operador instanceof.

Por ejemplo, si tenemos la siguiente jerarquía de clases, utilizaríamos el operador instanceof para realizar unas acciones u otras dependiendo del objeto que realmente tengamos:

public class Contrato{...}

 

 public class Deposito extends Contrato{...}

 

 public class Prestamo extends Contrato{...}

 

public void finalizarContrato(Contrato c){
    if (c instanceof Deposito){
        //Devolver intereses
        //Poner indicador de contrato vivo a falso
    }
    else if (c instanceof Prestamo){
        //Poner importePendiente a 0
        //Poner indicador de contrato vivo a falso
    }
}

¿Como podemos realizar estas acciones si para nuestro compilador c es de tipo Contrato y no podríamos acceder a métodos de Deposito y de Prestamo? Haciendo una conversión de tipos.

Conversión de tipos

En los casos como el anterior, en el que ya hemos comprobado mediante el operador instanceof que el objeto es una subclase concreta, es posible acceder a toda la funcionalidad del objeto convirtiendo la referencia.

Para el ejemplo anterior sería:

public void finalizarContrato(Contrato c){
    if (c instanceof Deposito){
        Deposito d = (Deposito) c;
        //Devolver intereses
        d.devolverIntereses();
        //Poner indicador de contrato vivo a falso
        d.setIndContratoVivo(false);
    }
    else if (c instanceof Prestamo){
        Prestamo p = (Prestamo)c;
        //Poner importePendiente a 0
        p.setImportePendiente(0);
        //Poner indicador de contrato vivo a falso
        p.setIndContratoVivo(false);
    }
}

Si no realizamos la conversión, cualquier llamada a un método provocará error al no localizar tal método en la superclase.

Debemos tener en cuenta:

  • Las conversiones en dirección ascendente (de un objeto de una subclase a una referencia a una superclase o interfaz) siempre están permitidas, y de hecho, no precisan el operador de conversión. Se pueden hacer mediante una simple asignación.
    Prestamo pr = new Prestamo();
    Contrato c = pr;  //"Padre" = "Hijo" siempre posible y no necesario cast.
    

    Si Prestamo implementa Firmable con el método firmar, también es legal la asignación directa:

    Prestamo pr = new Prestamo();
    Firmable f = prestamo;
    f.firmar(); //podremos llamar a los métodos de la interfaz,
    //ya que están implementados en Prestamo.
    

    Y más aún, si tenemos la clase PrestamoHipotecario que hereda de Prestamo, que implementa a Firmable, también podemos hacer la asignación directa. Ya que PrestamoHipotecario hereda también la función Firmar por Prestamo implementar a Firmable.

    PrestamoHipotecario hip = new PrestamoHipotecario();
    Firmable f = hip;
    f.firmar();
    
  • En las conversiones de dirección descendente (de un objeto de una superclase a una referencia a una subclase), el compilador debe poder considerar que la conversión es posible, para esto, la clase destino de la conversión tiene que ser una subclase del tipo de referencia actual.
    Contrato c = new Contrato();
    Prestamo p = (Prestamo) c; // "Hijo" = "Padre" necesita cast.
    //El compilador no dará fallo pues parece posible la conversión.
    //Prestamo es una subclase de Contrato.
    
    Empleado e = new Empleado();
    Prestamo p = (Prestamo) e; //En este caso el compilador considera
    //que es imposible la conversión. Ni siquiera está en la jerarquía.
    //Provocará un error 'Inconvertible types'
    
  • Si el compilador permite la conversión, todavía no podemos cantar victoria, el tipo de objeto se comprueba durante el tiempo de ejecución. Si el objeto que se va a convertir no es realmente del tipo al que se hace la conversión, se producirá un error en tiempo de ejecución. Será una excepción ClassCastException.
    Contrato c1 = new Contrato();
    Contrato c2 = new Prestamo();
    
    Prestamo p1 = (Prestamo) c1; //Compila pero genera ClassCastException al ejecutar.
    Prestamo p2 = (Prestamo) c2; //Compila y se ejecuta correctamente.
    
Anuncios
 
1 comentario

Publicado por en 12 mayo, 2011 en Estudio, Tema 2

 

Etiquetas: , , , ,

Una respuesta a “Orientación a objetos (IV) – Conversiones de tipos

  1. Rafael

    22 octubre, 2015 at 11:10 pm

    Hola, los comentarios del ultimo ejemplo están erroneos

     

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: