Downcast and Upcast

What is the difference between up-casting and down-casting with respect to class variable

Upcasting is casting to a supertype, while downcasting is casting to a subtype. Upcasting is always allowed, but downcasting involves a type check and can throw a ClassCastException.

In your case, a cast from a Dog to an Animal is an upcast, because a Dog is-a Animal. In general, you can upcast whenever there is an is-a relationship between two classes.

Downcasting would be something like this:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

Basically what you're doing is telling the compiler that you know what the runtime type of the object really is. The compiler will allow the conversion, but will still insert a runtime sanity check to make sure that the conversion makes sense. In this case, the cast is possible because at runtime animal is actually a Dog even though the static type of animal is Animal.

However, if you were to do this:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

You'd get a ClassCastException. The reason why is because animal's runtime type is Animal, and so when you tell the runtime to perform the cast it sees that animal isn't really a Dog and so throws a ClassCastException.

To call a superclass's method you can do super.method() or by performing the upcast.

To call a subclass's method you have to do a downcast. As shown above, you normally risk a ClassCastException by doing this; however, you can use the instanceof operator to check the runtime type of the object before performing the cast, which allows you to prevent ClassCastExceptions:

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;
}

Downcasts can be expressed more succinctly starting from Java 16, which introduced pattern matching for instanceof:

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
}

downcast and upcast

  1. That is correct. When you do that you are casting it it into an employee object, so that means you cannot access anything manager specific.

  2. Downcasting is where you take a base class and then try and turn it into a more specific class. This can be accomplished with using is and an explicit cast like this:

    if (employee is Manager)
    {
    Manager m = (Manager)employee;
    //do something with it
    }

or with the as operator like this:

Manager m = (employee as Manager);
if (m != null)
{
//do something with it
}

If anything is unclear I'll be happy to correct it!

What are the reasons upcasting and downcasting are used in C++?

When have a base class, from which several classes inherit, we often want a pointer that can point to one of those derived classes.

For example we can have an Animal class and derived Dog and Cat classes:

class Animal {};

class Dog : public Animal {};
class Cat : public Animal {};

Dog dog;
Animal* a = &dog;

Cat cat;
Animal* b = &cat;

Often times, we want to have a pointer that can pointer to one of these objects. We can use an Animal pointer, since both a Dog and a Cat are a type of Animal. This is the nature of upcast. We upcast a derived class and represent it as the base class.

What about downcasting? We can do so using a dynamic_cast:

Cat c;
Animal* animal = &c; //Implicit upcast
Cat* cat = dynamic_cast<Cat*>(animal); //Explicit downcast
//Check if dynamic cast worked:
if(!cat) {
//ERROR: Not a cat object
}

Upcasting/Downcasting in Java

With the implicit upcast at this line:

Animal myAnimal = myDog;

You are not doing anything to change the underlying instance myDog. What you are doing is assigning it to a variable of a type one level higher in the inheritance tree. Effectively, this restricts which methods can be called to only those defined in Animal, but does not change how those methods resolve.

Because you have restricted the methods available to only those defined on the parent class Animal, the compiler cannot resolve Dog#bark(), since it is a method of Dog, and the variable myAnimal is defined to be of type Animal which has no #bark method.

#move() is a method of both Animal and Dog, so it resolves, but it resolves to the method defined on Dog, since myAnimal still refers to an instance of Dog, despite being upcast.

Upcasting Downcasting

It's giving you an error because a isn't an instance of C - so you're not allowed to downcast it. Imagine if this were allowed - you could do:

Object o = new Object();
FileInputStream fis = (FileInputStream) o;

What would you expect to happen when you tried to read from the stream? What file would you expect it to be reading from?

Now for the second part:

A a=new A();
C c=new C();
C c=(C)a;

That will not work fine - for a start it won't even compile as you're declaring the same variable (c) twice; if you fix that mistake you'll still get an exception when you try to cast an instance of A to C.

This code, however, is genuinely valid:

A a = new C(); // Actually creates an instance of C
C c = (C) a; // Checks that a refers to an instance of C - it does, so it's fine


Related Topics



Leave a reply



Submit