Inheritance in Object Oriented Programming
Tags: oop, programming, python
Published: 2022-09-05 22:10:32

I was studying Object Oriented Programming concepts last week and I decided to share a sum up about one of them: inheritance.

**Inheritance**

Inheritance allows classes to share their attributes, methods and functionalities to other classes. So in order to link those classes inheritance adopts a hierarchical schema relationship.

In inheritance hierarchy we have the _parent_ class which is the class that gives its features to another class. They can also be called _base_ class or _super_ class.
On the other hand we have the _child_ class which is the class that inherits the features from another class. They can also be called _sub_ class or _derived_ class.

**And why is that relevant?**

Inheritance then makes it possible to create an increasingly specialized hierarchical structure of classes. The big advantage of this is not having to start from scratch to specialize an existing class. The child class should be a specific implementation of unique attributes/methods/functionalities from a more generic class that shares similarities.  So let’s go to a Python example.

Let’s say we create a class called _Person_ which has the _first_name_ and _last_name_ as attributes. That would cover a generic situation if we assume all people are likely to have a first name and a last name, right? Proceeding from that we also create a class called _Employee_. We can say all employees are also persons so we will make our _Employee_ class inherits the _Person_ class attributes and methods, so the _Person_ class will become _Employee’s_ parent class.  If we go a little further we also could create a class called, for example, _Developer_. And for our example we will assume that all developers are also employees so that they will inherit attributes and methods from its parent class (which in this case is the _Employee_ class). So we could write something like this:

![Class inheritance in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8d9o4t2b9xd39975ugou.png)

Note that the _Developer_ class inherits features from the _Employee_ class which is child of the _Person_ class. So the _Developer_ class also inherits the attributes and methods related to the _Person_ class. This is a **multilevel inheritance** situation.

**super()**
Also note that in addition to pass the parent class as an argument when creating the child class we also use the _super_ keyword as a reference to make our child classes to inherit the parent’s functionalities. So basically what we’re doing is using _super_ in our _constructor/init_ method and passing the attributes related to the parent class as arguments so they can be used in the parent’s class constructor.

**Method Overriding**

It’s basically to redefine a class method that is already defined in its parent class. So let’s go back to our previous example. Let’s say you want to change the greeting for the _Developer_ class but instead of creating a different method as we did (_dev_greeting_ method) we want to override the existing _greeting_ method. Now when calling the _greeting_ method for an instance of the _Developer_ class we would be calling the overridden _greeting_ method and would print out our overridden greeting:

![Method overriding example in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/benkmvzvxfbjsq1v36r5.png)
![Output from the overridden method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2g4l3k3e3t1ynfq0n76.png)

We could also add something else to the existing _greeting_ method, printing out the greeting from the parent class plus our specific greeting for the _Developer_ class. Like this:

![Second example of method overriding ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejhg8ifal1dislrj3tlt.jpg)

**Multiple Inheritance in Python**

In Python you will find _multiple inheritance_ which means a child class can have more than one parent class and it will inherit all the methods and attributes of all its parent classes. See the example below:

![Multiple inheritance example in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tb238k6l773abzuygp8l.png)

It’s also relevant to mention that when using the _super_ keyword and referencing any methods from the parent classes in the child class you will notice a behaviour called **Method Resolution Order (MRO)**.  For example, let’s say you use the _super_ keyword to reference a method from one of the parent classes in the child class and create an instance of this last one. The instance methods, including the ___init___ method, will be executed based on the order defined by the classes inheritance as shown in the example below:

![Method Resolution Order example in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ardtq3dazas10o2m05o.png)

So in this case when creating a _Child_ class instance, its _init_ method is read and references the parent classes _init_ methods too. But since the _Parent1_ class has no _init_ method, the MRO allows to go to the next parent class _init_ method to be resolved, which in order is the _Parent2_ class.

This behaviour can be really confusing depending on the complexity your code reaches. In other programming languages such as Java you're not allowed to use multiple inheritance in order to avoid possible runtime errors (like duck typing examples in Python). Things like inheriting from multiple classes that declare a method with the same name but with different signatures can be really confusing and complex to deal with if you don't track them properly. Which can also demand a lot of work and raise confusing runtime errors that are hard to deal with.