¿Cuál es la diferencia entre upcasting y downcasting con respecto a la variable de clase?
¿Cuál es la diferencia entre upcasting y downcasting con respecto a la variable de clase?
Por ejemplo, en el siguiente programa la clase Animal contiene solo un método pero la clase Perro contiene dos métodos, entonces cómo convertimos la variable Perro a la Variable Animal.
Si se realiza el casting, ¿cómo podemos llamar a otro método del Perro con la variable Animal?
class Animal
{
public void callme()
{
System.out.println("In callme of Animal");
}
}
class Dog extends Animal
{
public void callme()
{
System.out.println("In callme of Dog");
}
public void callme2()
{
System.out.println("In callme2 of Dog");
}
}
public class UseAnimlas
{
public static void main (String [] args)
{
Dog d = new Dog();
Animal a = (Animal)d;
d.callme();
a.callme();
((Dog) a).callme2();
}
}
Upcasting se convierte en un supertipo, mientras que downcasting se convierte en un subtipo. El upcasting siempre está permitido, pero el downcasting implica una verificación de tipo y puede generar un archivo ClassCastException
.
En su caso, una conversión de a Dog
a an Animal
es una conversión ascendente, porque a Dog
es-a Animal
. En general, puede realizar upcast siempre que exista una relación entre dos clases.
Downcasting sería algo como esto:
Animal animal = new Dog();
Dog castedDog = (Dog) animal;
Básicamente, lo que estás haciendo es decirle al compilador que sabes cuál es realmente el tipo de tiempo de ejecución del objeto . El compilador permitirá la conversión, pero aún así insertará una verificación de validez del tiempo de ejecución para asegurarse de que la conversión tenga sentido. En este caso, la conversión es posible porque en tiempo de ejecución animal
es en realidad a Dog
aunque el tipo estático de animal
sea Animal
.
Sin embargo, si tuvieras que hacer esto:
Animal animal = new Animal();
Dog notADog = (Dog) animal;
Obtendrías un ClassCastException
. La razón es porque animal
el tipo de tiempo de ejecución es Animal
, por lo que cuando le dice al tiempo de ejecución que realice la conversión, ve que animal
en realidad no es a Dog
y, por lo tanto, lanza a ClassCastException
.
Para llamar al método de una superclase, puede hacerlo super.method()
o realizando el upcast.
Para llamar al método de una subclase hay que hacer un downcast. Como se muestra arriba, normalmente corres el riesgo ClassCastException
de hacer esto; sin embargo, puede utilizar el instanceof
operador para verificar el tipo de tiempo de ejecución del objeto antes de realizar la conversión, lo que le permite evitar ClassCastException
s:
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
// Guaranteed to succeed, barring classloader shenanigans
Dog castedDog = (Dog) animal;
}
Los downcasts se pueden expresar de manera más sucinta a partir de Java 16, que introdujo la coincidencia de patrones parainstanceof
:
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog castedDog) {
// now castedDog is available here as in the example above
}
El downcasting y el upcasting fueron los siguientes:
Upcasting : cuando queremos convertir una subclase en superclase, utilizamos Upcasting (o ampliación). Sucede automáticamente, no es necesario hacer nada explícitamente.
Downcasting : cuando queremos convertir una superclase en una subclase, usamos Downcasting (o estrechamiento), y Downcasting no es directamente posible en Java, tenemos que hacerlo explícitamente.
Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException
Autoboxing versus Casting