Buenos días, hombre Javarash. Comencé a recibir preguntas sobre la conversión de tipos de referencia en Java. Para no contar cada vez lo mismo, decidí escribir un breve artículo.
Primero, veamos qué es el casting de tipos.
La conversión de tipos (conversión de tipos) es la conversión de un valor de variable de un tipo a un valor de otro tipo. Veamos un ejemplo de qué es y con qué se come. Tenemos cierta jerarquía de clases ( ver Figura 1 ). Aquí puedes ver todas las clases de la jerarquía, quién hereda a quién y los métodos de cada clase. Hay una aducción que se expande y otra que se contrae. Vemos que la claseCat
es descendiente de la clase Pet
. Pet
, a su vez, es un sucesor de la clase Animal
. Cuando escribimos:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Esta es una conversión en expansión (o implícita). Hemos ampliado los enlaces animalCat
y animalDog
. Se refieren a objetos Cat
y Dog
. Con tal conversión, no podemos animalCat/animalDog
llamar a métodos a través de un enlace que están en Cat/Dog
, pero que no están en Animal
. Una tendencia estrecha (o explícita) ocurre en la dirección opuesta:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Cat cat =(Cat)animalCat;
YorkshireTerrier dog = (YorkshireTerrier) animalDog;
Hemos indicado claramente a qué tipo queremos convertir este objeto. ¡¡¡PERO TEN CUIDADO!!! Si lo haces así:
Animal animalCat = new Cat();
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
el compilador omitirá este código. Pero RunTime
te echará:
Exception in thread "main" java.lang.ClassCastException: Animals.Cat cannot be cast to Animals.YorkshireTerrier
RunTime
Ve que Cat
hay YorkshireTerrier
dos clases diferentes. Para evitar ClassCastException durante la conversión restringida, utilice instanceof
.
Animal animalCat = new Cat();
if (animalCat instanceof YorkshireTerrier)
{
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
}
Si animalCat
es así YorkshireTerrier
, entonces se realizará la asignación; si no, no sucederá nada.
Ahora bien, ¿por qué es esto necesario si perdemos métodos y podemos obtener este tipo de errores?
Veamos el código que hice según el diagrama de la Fig. 1 . ClaseAnimal
public abstract class Animal
{
String name;
int age;
String nameOfClass = getClass().getSimpleName();
public void eat(){
System.out.println(nameOfClass + ": Omnomnom");
}
public void sleep(){
System.out.println(nameOfClass + ": Z-z-z-z");
}
}
Una clase WildAnimal
que hereda deAnimal
public abstract class WildAnimal extends Animal
{
public void steelChicken()
{
System.out.println(nameOfClass+": Muhaha,I stole a chicken!");
}
}
Una clase Pet
que hereda deAnimal
public abstract class Pet extends Animal
{
public void peeInTray(){
System.out.println(nameOfClass + ": Master, I peed");
}
}
Una clase Fox
que hereda deWildAnimal
public class Fox extends WildAnimal
{
public void eatColobok(){
System.out.println(nameOfClass + ": I will eat you, Colobok");
}
}
Una clase Wolf
que hereda deWildAnimal
public class Wolf extends WildAnimal
{
public void hawlAtTheMoon(){
System.out.println(nameOfClass + ": Ouuuuu!!!Ouuuu!!!");
}
}
Una clase Cat
que hereda dePet
public class Cat extends Pet
{
public void sleepOnKeyboard(){
System.out.println(nameOfClass + ": Master, stop working!!I wanna sleep on your keyboard");
}
}
Una clase YorkshireTerrier
que hereda dePet
public class YorkshireTerrier extends Pet
{
public void bark(){
System.out.println(nameOfClass + ": Meow!!! Meow!!!");
}
}
Imagínese la situación. Necesitamos reunir a todos los animales en una lista, alimentarlos y luego acostarlos. Esto es fácil de hacer si creamos ArrayList
animales ( Animal
). Y luego llamamos a los métodos correspondientes para cada animal:
public class ZOO
{
public static void main(String[] args)
{
List<Animal> allAnimals = new ArrayList<>();
allAnimals.add(new Cat());
allAnimals.add(new Wolf());
allAnimals.add(new Fox());
allAnimals.add(new YorkshireTerrier());
for (Animal animal : allAnimals)
{
animal.eat();
animal.sleep();
}
}
}
No puedo animal
llamar al método bark()
o sleepOnKeyboard()
. Porque la hoja allAnimals
contiene un gato, un lobo, un yorick y un zorro, pero se reducen a Animal
. Y solo tienen los métodos que están en Animal
. Esto es muy bueno, porque si pudiéramos llamar a todos los métodos, ¿por qué necesitamos un lobo que duerma en el teclado o un yorick que robe gallinas? Gracias por su atención. Espero que este artículo te sea útil. Se aceptan críticas y comentarios)
GO TO FULL VERSION