Search code examples
c#inheritanceinstantiation

What's the difference between instantiating a derived object as the base type compared to instantiating it as the derived type?


What is the difference in the code below between instantiating circle as type Shape and rectangle as type Rectangle?

Shape is the base class, Circle and Rectangle are both derived from Shape. Each instantiation is commented with what the VS Code debugger shows as the variable information.

I'm not sure if I'm using the right terminology; I've been learning C# for a bit over a month so forgive me if I'm not.

var shape = new Shape(); // shape = {Shape}
Shape circle = new Circle();  // circle [Shape] = {Circle}
Rectangle rectangle = new Rectangle(); // rectangle = {rectangle}

class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}

Solution

  • The difference is that Circle and Rectangle are interchangeable as Shape, but Rectangle and Circle are not interchangeable on their own.

    In other words you can create a typed array of Shape objects and add both Rectangle and Circle to it:

    Shape[] shapes = new Shape[2];
    
    shapes[0] = circle;
    shapes[1] = rectangle;
    

    But your Rectangle and Circle classes don't add anything, so it's not very useful.

    What you're doing is called inheritance. Your Shape class is called the base class. And your Circle and Rectangle classes are called the derived classes. Inheritance allows you have:

    1. Shared behavior between objects.
    2. Override that behavior if needed in the derived classes using virtual and override methods.
    3. Add specific/unshared behavior to the derived classes.

    Let's say your Shape class looked like this:

    class Shape {
      public void Draw() { ... }
    }
    

    Now you can implement drawing on screen logic and call rectangle.Draw() and circle.Draw() on the array we made above:

    foreach (Shape shape in shapes) {
      shape.Draw();
    }
    

    To finish it off, let's add something specific to Circle:

    class Circle : Shape {
      public double Radius { get; set; }
    }
    

    A Rectangle doesn't a radius, so it makes sense to derive from Shape and add our Radius property in Circle specifically.

    Note that this won't work:

    foreach (Shape shape in shapes) {
      // will not compile because Radius is only defined in Circle
      var radius = shape.Radius;
    }
    

    More information: https://www.programiz.com/csharp-programming/inheritance