Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upcasting and its effect on the heap

For the following classes:

public class Parent {
//Parent members
}

public class ChildA : Parent {
//ChildA members
}

public class ChildB : Parent {
//ChildB members
}

If I upcast ChildA or ChildB instance to a Parent instance, then I can't accesses their members, but their members are still there, because if I downcast and try to access their members again I will find that they still have their data.

I think this means that the Parent Instance keep allocating memory for the Child classes.

So does this mean when I instantiate a Parent Class that its allocating memory for the child classes members, or is that just happening when I cast?

And is it possible for a parent to allocate memory for more than one child if we go backward and forward with casting?

like image 759
Honey Avatar asked Nov 20 '17 10:11

Honey


People also ask

What is the purpose of Upcasting?

Upcasting is the typecasting of a child object to a parent object. Upcasting can be done implicitly. Upcasting gives us the flexibility to access the parent class members but it is not possible to access all the child class members using this feature.

What happens in Upcasting Java?

In Upcasting, we assign a parent class reference object to the child class. In Java, we cannot assign a parent class reference object to the child class, but if we perform downcasting, we will not get any compile-time error. However, when we run it, it throws the "ClassCastException".

Does casting allocate memory?

4 Answers. In the case you describe above, casting does not affect the memory that is allocated when casting from base to sub class and vice versa. If you instantiate a Parent you will have a Parent object in memory.

What is Upcasting in C?

It is the process to create the derived class's pointer or reference from the base class's pointer or reference, and the process is called Upcasting. It means the upcasting used to convert the reference or pointer of the derived class to a base class.


3 Answers

"Normal" Upcasting and Downcasting of Reference Types

For reference types, casting variables doesn't change the type of the object already allocated on the heap, it just affects the type of the variable which references the object.

So no, there isn't any additional heap overhead with casting reference types (i.e. object instances from classes) provided that there are no custom conversion operators involved (See below, tolanj's comment).

Consider the following class hierarchy:

public class Fruit
{
    public Color Colour {get; set;}
    public bool Edible {get; set;}
}

public class Apple : Fruit
{
    public Apple { Color = Green; Edible = true; KeepsDoctorAtBay = true;}
    public bool KeepsDoctorAtBay{get; set;}
}

Which, when used with both upcasting and downcasting:

Example of variables pointing to same heap object

There is only ever one allocation on the heap, which is the initial var foo = new Apple().

After the various variable assignments, all three variables, foo, bar and baz point to the same object (an Apple instance on the heap).

Upcasting (Fruit bar = foo) will simply restrict the variable's available access to only Fruit methods and properties, and if the (Apple)bar downcast is successful all methods, properties and events of the downcast type will be available to the variable. If the downcast fails, an InvalidCastException will be thrown, as the type system will check the type of the heap object's compatability with the variable's type at run time.

Conversion Operators

As per tolanj's comment, all bets about the heap are off if an explicit conversion operator replaces the default casting of reference types.

For instance, if we add an unrelated class:

public class WaxApple // Not inherited from Fruit or Apple
{
    public static explicit operator Apple(WaxApple wax)
    {
        return new Apple
        {
            Edible = false,
            Colour = Color.Green,
            KeepsDoctorAtBay = false
        };
    }
}

As you can imagine, WaxApple's explicit operator Apple can do whatever it likes, including allocate new objects on the heap.

var wax = new WaxApple();
var fakeApple = (Apple)wax;
// Explicit cast operator called, new heap allocation as per the conversion code. 
like image 69
StuartLC Avatar answered Sep 30 '22 22:09

StuartLC


In the case you describe above, casting does not affect the memory that is allocated when casting from base to sub class and vice versa.

If you instantiate a Parent you will have a Parent object in memory. If you cast that to either of the child classes it will fail with an InvalidCastException.

If you instantiate either child you will have a child object in memory. You can cast this to the Parent and then back again. The memory allocation does not change in either case.

Additionally, if you instantiate a ChildA, cast to Parent and then attempt to cast to ChildB, you will get an InvalidCastException

like image 31
Tim Rutter Avatar answered Sep 30 '22 20:09

Tim Rutter


A (down-)cast is nothing but a view onto an instance of a class by the "eyes of the parent class". Thus you´re neither losing nor adding any information nor memory by casting, you simply reference the same memory allready allocated for the original instance. This is the reason why you can still access (e.g. by reflection) the members of ChildA in the variable of type Parent. The information still exists, it is simply not visible.

So instead of having two memory-allocations you have two memory-references.

However be aware that this does not apply if you provide your own cast, e.g. from ChildA to ChildB. Doing so will typically look more or less similar to this:

public static explicit operator ChildA(ChildB b)
{
    var a = new ChildA((Parent)b);
    /* set further properties defined in ChildA but not in ChildB*/
}

Here you have two completely different instances, one of type ChildA and one of type ChildB which both consume their own memory.

like image 28
MakePeaceGreatAgain Avatar answered Sep 30 '22 21:09

MakePeaceGreatAgain