Vamos a ver cómo castear variables entre diferentes clases relacionadas y argumentos de tipo en métodos.
Este apartado es bastante complejo y de nivel avanzado. Por orden, toca explicarlo aquí, pero recomiendo hacerlo al final. No se usará durante lo que queda de curso.
Casting
El casting es una técnica en Java que nos permite convertir un tipo de objeto en otro. En el contexto de la herencia e interfaces, el casting se vuelve especialmente útil.
Esto no significa que mágicamente se pueda convertir una variable a otro tipo, sino que esa variable se puede convertir a otro tipo que estaba relacionado anteriormente con su tipo original.
Esta técnica se hace poniendo entre paréntesis ()
el tipo de variable al que quieres convertir un objeto.
Por ejemplo, para convertir un int
en double
y poder dividir con decimales, usamos el cast de la siguiente manera:
int numero = 10;
double resultado = 5 / (double) numero;
Al realizar (double) numero
, la variable numero
(int
) pasa a ser un double
en ese contexto.
Instance Of
El operador instanceof
en Java se utiliza para verificar si un objeto es una instancia de una clase o interfaz específica. Este operador devuelve true
si el objeto es una instancia de la clase o interfaz especificada, o false
si no lo es.
Sabemos que Car
o Truck
son Vehicle
, por eso en nuestro Main
podemos realizar lo siguiente:
package me.polvallverdu.course;
import me.polvallverdu.course.vehicles.Car;
import me.polvallverdu.course.vehicles.Vehicle;
import me.polvallverdu.course.vehicles.VehicleColor;
public class Main {
public static void main(String[] args) {
Vehicle vehiculo = new Car(VehicleColor.RED);
}
}
Al Car
extender Vehicle
, esto no causará ningún fallo. Ahora bien, si queremos volver a tener una instancia de Car
de forma segura, para interactuar con su interfaz de MusicRadio
(solo en Car
, no en Vehicle
), usamos instanceof
.
package me.polvallverdu.course;
import me.polvallverdu.course.vehicles.Car;
import me.polvallverdu.course.vehicles.Vehicle;
import me.polvallverdu.course.vehicles.VehicleColor;
public class Main {
public static void main(String[] args) {
Vehicle vehiculo = new Car(VehicleColor.RED);
if (vehiculo instanceof Car) {
Car coche = (Car) vehiculo;
coche.playMusic();
}
}
}
O simplificado:
package me.polvallverdu.course;
import me.polvallverdu.course.vehicles.Car;
import me.polvallverdu.course.vehicles.Vehicle;
import me.polvallverdu.course.vehicles.VehicleColor;
public class Main {
public static void main(String[] args) {
Vehicle vehiculo = new Car(VehicleColor.RED);
if (vehiculo instanceof Car coche) {
coche.playMusic();
}
}
}
También podemos comprobar directamente si vehiculo
implementa nuestra interfaz MusicRadio
:
package me.polvallverdu.course;
import me.polvallverdu.course.vehicles.Car;
import me.polvallverdu.course.vehicles.MusicRadio;
import me.polvallverdu.course.vehicles.Vehicle;
import me.polvallverdu.course.vehicles.VehicleColor;
public class Main {
public static void main(String[] args) {
Vehicle vehiculo = new Car(VehicleColor.RED);
if (vehiculo instanceof MusicRadio radio) {
radio.playMusic();
}
}
}
Argumentos de Tipo
Los argumentos de tipo son una característica de Java que permite especificar el tipo de dato que se espera para un argumento y que pueda ser más dinámico.
Para nuestro ejemplo MusicRadio
, si quisiéramos aceptar cualquier argumento que implemente MusicRadio
, podemos crear un método para iniciar la radio usando Argumento de Tipo:
public static<T extends MusicRadio> void playMusic(T musicRadio) {
musicRadio.playMusic();
}
Este método aceptará como argumento cualquier clase que implemente MusicRadio
, independientemente de si es Car
o cualquier alternativa, y encima, el tipo T
dará acceso a todos los métodos de MusicRadio
.