Polymorphism & Casting (OOP) Explained

Robert Long
4 min readAug 30, 2020

--

Inheritance in Object-Oriented Programming creates an IS-A relationship between objects. You can think of these relationships like a family tree — a parent to child— relationship where genes from the parents are passed to their children. Except it goes a step further to say that the parent type is the same as the child type.

For instance, say we have a base class called Animal. Next, say we have 3 child classes that inherit from Animal: Human, Spider, and Bear.

credit to Intully

As we know, the child classes will inherit the code from the base class. Moreover, the child classes are also the same type as the parent class. That is to say, a Human is an Animal, a Spider is an Animal, and a Bear is an Animal. Any classes that inherit from the Animal type is itself an Animal type. In in other words, Animal type can be a Human, a Spider, or a Bear. This ability for Animal to become these various types is called polymorphism.

As a consequence of this, when you have a chain of hierarchies, you will inevitably deal with type polymorphism. But what if you are have a Spider object and would like to go back to an Animal type? By casting, you can turn the Spider type into it’s Animal base class. Likewise, you can take this same object and cast it back to it’s Animal type. In this way, casting allows us to traverse through the inheritance hierarchy.

Type Polymorphism

Type polymorphism is useful for parameters or lists that can contain a different variety of the specific type.

For instance, let’s use the Animal example from earlier. One way we can utilize type polymorphism is to create a list called ZooAnimals.

Animals[] ZooAnimals = new List<Animals>() 
{
new Human("Homer"),
new Spider("Charlotte"),
new Bear("Smokey")
}

In this example, we have created a list that contains 3 different types of Animals. Notice how are list’s type is Animal, but the elements instantiate specific Animal types. Human, Spider, and Bear are allowed to be in this list because they are descendants of the Animal type.

Likewise, functions can also make use of polymorphism in the form of parameter types or return types.

For instance, say that we are writing a game where we are using this Animal type which has a HitPoint field and a MaxHitPoint field both of integer type. We can implement a Heal function which restores life 1 life to our Animal.

public void Heal(Animal hero)
{
if(hero.MaxHitPoint > hero.HitPoint)
hero.HitPoint += 1;
}

Notice here that our Animal is our hero, which by definition, can be either a Human, a Bear, a Spider, or anything that inherits from the Animal class.

Type Casting

Through our previous example, we know that Humans are Animals and that Animals can possibly be a Human, a Bear, a Spider or any type inherited from Animal base class. We are allowed to transform our data type up or down the hierarchy chain through casting.

Upcasting allows us to go from a child type back to it’s base type.

credit to Intully

Downcasting allows us to go from a base type to a specific type. This can fail because the child type any multitude of types that inherit from the base class. It is best practice to check whether a type is indeed that child type before casting it.

What if we have an Animal type that we know is a Human type?

For instance, say we have a Move function that animates our hero in a specific direction. By default, this will invoke the Crawl function, but for Humans, we want it to invoke the Walk function instead. We are provided with an array of Animals and we don’t know which element in this list is Human. How could we handle this?

First we need to go through the list and check if the element is Human, if it is, then we can handle it separately by casting it to Human type and invoking the the Walk function, otherwise we invoke the Crawl function for other Animal types.

public void Move(Animal hero, Direction dir)
{
if(hero is Human)
hero.Walk(dir)
else
hero.Crawl(dir)
}

--

--