Why Use Inheritance?

Why use inheritance

Inheritance is a term for reusing code by a mechanism of passing down information and behavior from a parent class to a child or sub class. It’s pretty easy to understand really. Just like a child can inherit various mannerisms and behaviors from his or her biological parents, in software this same concept holds true. By leveraging the power of inheritance and creating child classes that extend their parent, we can make sub classes with super powers that have everything their parent has and more. Let’s take a look at how inheritance works in PHP.

The extends keyword

Any time you see the extends keyword in use, you know that inheritance is being used. Following along the biological example of inheritance, we can see how a Son might inherit from a Father.

As we can see in the example, when we new up, or instantiate a Son object, we are able to make use of the getGender() method. If you look in the Son class however, it is a blank slate with nothing in there. How are we able to make use of that method? We can make use of the getGender() method because of Inheritance. Specifically, the Son class inherits from the Father class. This is exactly why we use inheritance. We use it for when we want to inherit behavior from a parent class. Of course since people love jargon so much, the parent class could also be referred to as the base class or super class. The child class goes by things such as the derived class, the sub class, or the heir class. They all mean the same thing.

Frameworks Use Inheritance

The reason why Frameworks in programming are so popular, is because we get to make use of well tested software without having to reinvent the wheel by use of inheritance. For example, in the Laravel PHP Framework, in order to make use of the popular Eloquent Active Record implementation, our class needs to extend Model. When you extend model like so:

You now get access to all of the methods found at this link, and it’s a lot of them! So by writing about two lines of code, you get to access hundreds of extremely helpful methods. Sounds like a good deal, right? That is exactly what inheritance is for.

Implementing Shared Behavior

In addition to code reuse, inheritance is good for the ability to implement shared behavior. Consider a Vehicle class. All vehicles will have wheels, and we should be able to fetch the number of wheels for any given vehicle. So let’s add a getWheels() method to our parent class.

Hmm… Notice a problem there? We want to make use of inheritance to make fetching the number of wheels from any of our Vehicles easier. The problem is, the algorithm to fetch the number of wheels for a Car versus a Unicycle is different. So it would seem that we can’t place just one method in the parent class and expect all the sub classes to be able to use it successfully in this case. How can we overcome this?

Shared Behavior Design

By looking at our collection of vehicles, we can see that a Motorcycle and a Segway could probably make use of the same algorithm. This is to say, both of them have two wheels. So if we have a case where the same algorithm can solve a problem for more than one type of sub class, then we can put that common behavior in the parent class. Let’s take care of that now.

Method Overriding

The prior example is a good solution to sharing behavior, but it also introduces a problem. Our Car class currently extends the Vehicle class. The Vehicle class has a dedicated method for fetching the number of wheels of our Vehicle. Let’s try out the method on an instance of the Car class.

Whoops. It looks like our software has a bug. We called the getWheels() method on our Car class and it returned a value of Two Wheels. Cars don’t have Two Wheels, they have Four. In this case, we need to provide the Car class with it’s own implementation of the getWheels() method, and we can do this by replacing or overriding the method of the parent class. We’ll just make one small change to our Car class to get it working correctly.

Now, even though the Car class inherits from the Vehicle class, it is able to return the correct number of wheels for a Car since it has it’s own implementation of the getWheels() method. Any time you need a unique behavior for a sub class, you can easily override methods of the parent class.

What If All Sub Classes Are Unique?

Let’s imagine that we only have a Car, Motorcycle, and a Unicycle. We still have our Vehicle class that we want to extend from. Is there anything to be gained from trying to implement a shared behavior in the parent class at this point? There is no shared behavior any more, so probably not. We no longer have a shared behavior, but it would still be nice to be able to fetch the number of wheels from our three different types of Vehicles. There are two reasons why a Vehicle parent class might still be useful.

  • 1. Will there be any attributes that could be shared across every Vehicle? If so, put this in the parent class to prevent having to write the same thing multiple times in the sub classes.
  • 2. Do you still want the ability to implement a specific behavior on all sub classes, even if each implementation is different? If so, you can force this by way of a contract in an abstract class with the template method design pattern.

Let’s add these two ideas to our abstract parent Vehicle class.

What this code does is implement the ability to both set a color, and retrieve the color of any sub class that extends from Vehicle. This way, you only need to write the code in the constructor and set up a getter once, in the parent class. You will not need to write this over and over in the sub classes. We also have implemented an abstract protected method which forces sub classes to declare their own implementation of a getWheels() method. This is kind of similar to how an interface works. If we try to make a class that extends from Vehicle and we don’t include a getWheels() method, an exception will be thrown. Let’s see.

If we behave ourselves however, and follow the contract, all is well.

Why Use Inheritance Summary

In this tutorial we had a good luck at one of the bread and butter concepts of object oriented programming, and that is making use of inheritance. Being the lazy lot that we are, developers love to make good use of anything that can make our lives easier and prevent us from having to re invent the wheel. Inheritance helps us with just that task. You may also be interested in the new ES6 Inheritance features to learn about.