C# Inheritance & Object Conversion Tutorial

In this tutorial we learn how to inherit functionality from one class to another without rewriting the code.

We also cover object conversions and how to implicitly upcast and explicitly downcast an object.

What is inheritance

Another one of the three core principles, or pillars, in any object oriented program is inheritance. Inheritance is a relationship between two classes that allows one class to inherit code from the other.

Inheritance is usually referred to as an Is-A relationship. For example: a car is a vehicle, or a dog is an animal.

Inheritance allows for code reuse. We encapsulate common code in one class, and reuse that code in another. Inheritance also provides polymorphic behavior, which is extremely powerful.

How to inherit from a class

Any existing class is ready to be inherited from, we don’t need to do anything special to it.

This class is called the base class, super class or the parent class. The class that inherits from the base class is called the derived class, child class or sub class.

To inherit from another class, we specify the child class name followed by the colon operator and the parent class name.

Syntax:
access class parentIdentifier
{
    // parent class code
}

access class childIdentifier : parentIdentifier
{
    // child class code
}

The child class definition reads: childIdentifier inherits from parentIdentifier. This is important because interfaces have the same syntax, however, an interface is implemented, not inherited.

Example:
using System;

namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            // child class
            Dog myDog = new Dog();
            myDog.Growl();

            // access from parent class
            myDog.legs = 4;
            myDog.Walk();
            Console.WriteLine("myDog has {0} legs", myDog.legs);

            Console.WriteLine();

            // child class
            Duck myDuck = new Duck();
            myDuck.Quack();

            // access from parent class
            myDuck.legs = 2;
            myDuck.Walk();
            Console.WriteLine("myDuck has {0} legs", myDuck.legs);

            Console.ReadLine();
        }
    }

    class Animal
    {
        public int legs { get; set; }

        public void Walk()
        {
            Console.WriteLine("Animal parent class: All animals can walk");
        }
    }

    class Dog : Animal
    {
        public void Growl()
        {
            Console.WriteLine("Dog child class: A dog can growl, but a duck can't");
        }
    }

    class Duck : Animal
    {
        public void Quack()
        {
            Console.WriteLine("Duck child class: A duck can quack, but a dog can't");
        }
    }
}

In the example above we created a normal class, Animal, as the parent class. We also created two types of animal classes that inherit from Animal.

A common property that animals have are legs, and a common function would be to walk, so these are in the parent class.

A dog can growl, but can’t quack, so growling belongs to the dog child class. Similarly a duck can quack but can’t growl, so it belongs to the duck child class.

When we instantiate objects for each of the child classes, we have all the properties and functions of the parent class available to us.

The legs property, for example, is accessible to both the Duck and Dog child classes, and we can use and modify them.

Class object conversion (casting)

At some point in our application we’ll need to convert one class to another. We learned about type casting in the type conversions tutorial, and because a class is essentially a type, object casting is very similar.

How to upcast a class object

The conversion from a child class to a parent class is called upcasting, and is implicit.

Syntax:
parentIdentifier = childIdentifier;
Example:
using System;

namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Rectangle rectangle = new Rectangle();

            // upcast child class into parent class
            Shape shape = rectangle;
        }
    }

    public class Shape { }
    public class Rectangle : Shape { }
}

How to downcast a class object

The conversion from a parent class to a child class is called downcasting, and is explicit. There are two ways to downcast:

  • With cast expressions
  • With the as and is keywords

We need to explicitly tell the compiler that we want to cast the parent class to the child class. We do this by way of a cast expression, providing the class between parentheses as a prefix.

Syntax:
childIdentifier = (childType)parentIdentifier;

We use the childType with the parentIdentifier.

Example:
namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Shape shape = new Shape();

            // downcast parent class into child class
            Rectangle rectangle = (Rectangle)shape;
        }
    }

    public class Shape { }
    public class Rectangle : Shape { }
}

In the example above we downcast the Shape parent class into the Rectangle child class by using a cast expression.

If one cast is not compatible, the compiler will generate a InvalidCastException. To prevent this, we use the as keyword.

Syntax:
childIdentifier = parentIdentifier as childType;

if(parentIdentifier != null)
{
    // conversion success
}

If the conversion fails in this situation, it will return null instead of an error. So, we check if the conversion succeeded with a conditional if statement.

Example:
namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Shape shape = new Shape();

            // downcast parent class into child class
            Rectangle rectangle = shape as Rectangle;
            if(rectangle != null)
            {
                // conversion success
            }
        }
    }

    public class Shape { }
    public class Rectangle : Shape { }
}

In the example above, we downcast Shape to Rectangle and check if the conversion succeeded.

The is keyword checks if the conversion from one type to another is compatible. The is keyword is in many cases more concise than using the as keyword.

Syntax:
objectTypeTo is objectTypeFrom;

The is keyword will return a boolean of either true or false.

Example:
namespace Classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Shape shape = new Shape();
            Rectangle rectangle = new Rectangle();

            if(rectangle is Shape)
            {
                rectangle = shape as Rectangle;
                if (rectangle != null)
                {
                    // conversion success
                }
            }
        }
    }

    public class Shape { }
    public class Rectangle : Shape { }
}

In the example above, we check if a Rectangle is a Shape, and if so we downcast it.

Summary: Points to remember

  • Inheritance is where we define a class that inherits all the functionality from another class.
    • When a child class inherits from a parent class, the child class is linked to it and changes to the parent class may impact the child class.
  • We can convert objects of one class into object of another, known as object casting.
    • We implicitly upcast a child class to a parent class with the assignment operator.
    • We explicitly downcast a parent class to a child class with either a casting expression, or the as and is keywords.