Diving into Simple Inheritance using Python
Object Oriented Thinking : Inheritance
In the previous article, I had introduced the thought process behind object oriented approach. The article also had brief discussions around classes, attributes, methods and objects.
In this notebook, I have touched upon the basic implementation of the OOPs concept of Inheritance in Python.
Take a deep breath, Happy OOPs, Happy Inheritance (:
Thanks to realpython.com for some thoughtful insights
Inheritance refers to the process of obtaining something from someone. Here the giver and taker usually belong to a hierarchical tree. A simple example of inheritance could be a child inheriting the hair color from a parent. Here the parent and child are obviously a part of the hierarchy, a family, parent is the giver and child is the taker.
The same can be translated to programming also. Here instead of hair color, one class can inherit information from the other class. The information could be the attributes or methods or both.
In OOP terminologies, the source class from which the information is inherited is called as the ‘PARRENT’ class while the other class which inherits the information is called as the ‘CHILD’ class.
The information transfer can happen through different paths, for example, one PARENT class to one CHILD class (simple inheritance), multiple PARENT classes to one CHILD Class (multiple inheritance), one PARENT class to many CHILD classes and so on.
In this notebook, we will focus on SIMPLE INHERITANCE to understand the basic inheritance concepts and then finally dive into MULTIPLE INHERITANCE.
Why Inheritance ??
Well, we were happy with functions and modules, then as an improvisation, we moved to OOPs using Classes and Objects to improve modularity of the code. Then we started using ‘Abstraction’ to hide unnecessary information from users.
Now why are we even bothering to learn about INHERITANCE ?
The ideology of classes and objects is to group similar entities under the same roof. Imagine, what if further subgrouping is possible where most of the information in the downstream groups are going to flow down from the top most class.
For example, we all know dogs, lions and bears fall into the category of animals. Based on what we previously discussed, I can use a class to describe the attributes and methods of an animal and then create further objects to capture different attribute values for dogs, lions and bears.
Now consider, I want to deal with different breeds of dogs. Does it really sound meaningful to have different objects for each breed of a dog from animal class. ?? Sounds a bit disturbing, right ??
Inheritance to the rescue. I can create classes for dogs, lions and bears as CHILD classes of single PARENT animal class, then further downstream create CHILD class for each type of animal to get their breeds. When we do this, all the information passed on-to the PARENT animal class will be flowed down to all downstream CHILD classes, we avoid repeating the features addition.
Advantage of inheritance is that, CHILD classes can always modify the inherited data and also extend the list of attributes and methods within them without impacting the PARENT class. Sounds meaningful, Yes ?? For me, it does (;
Crisply speaking, CHILD classes can override or extend the attributes and methods of parent classes. In other words, CHILD classes inherit all of the PARENT’s attributes and methods but can also specify attributes and methods that are unique to themselves.
Let us move into the Python part now…
As discussed, simple inheritance refers to the case where ONE CHILD class inherits information from ONE PARENT class.
For the coding purposes, let us stick to basics of geometry and shapes.
PARENT Class Specs
The PARENT class ‘polygon’ takes just one argument as input from the user at the time of initialization, the number of sides of the polygon. it has two methods, one to get the length of all sides of the polygon, second to estimate the perimeter.
Input and perimeter functions are called from within the init(). Just a simple initialization of the class is enough to execute it.
PARENT class is just another class. Inheritance implementation starts only when a new class is defined as CHILD class to another PARENT class
PARENT Class Definition
PARENT Class Initialization
Simple Inheritance Implementation
For any polygon, regardless of the number of sides (obviously greater than or equal to 3), the perimeter is the sum of length of each side. Why define different classes to achieve the same. A different object can do the job.
But let us consider the case of polygon area, we need different methods for different shapes. But, area calculation can be done using the same information provided. We do not need to take the pains of getting all the details again.
As you guessed rightly, I am going to inherit the polygon class into downstream CHILD classes for specific shapes.
super() Quick Introduction
Well, we need to understand what a super() is before we proceed with inheritance.
super() is the proxy function which returns the PARENT class of a particular CHILD class. We use super() to initialize the init() of the PARENT class from within the CHILD class.
super() does much more than just search the parent class for a method or an attribute. It traverses the entire class hierarchy for a matching method or attribute. If you aren’t careful, super() can have surprising results. We will discuss super() in detail before going into MULTIPLE INHERITANCE.
For the time being, to keep it simple, in case of SIMPLE INHERITANCE, where ONE CHILD class is inheriting information from ONE PARENT class, super(). will search for the specified method within the PARENT class.
CHILD Class Definition
The PARENT class is provided as an argument within the CHILD class definition.
Key Points to Remember
1) While defining the init() for the child class, ensure all the parameters required for the parent class as well as new ones defined for the CHILD class are available in the init() signature.
2) While calling the PARENT init() within the CHILD init() using the super(), supply the PARENT Class parameters obtained in point 1 as arguments to the PARENT class init()
For example, Consider the following PARENT class init() signature is defined as : def _ _init _ _ (self, parameter1, parameter2)
CHILD Class needs additional information, say, parameter3
CHILD class definition should be as follows:
class CHILD(PARENT): def _ init (self, parameter1, parameter2, parameter3): super(). init _(self, parameter1, parameter2)
Refer, code blocks for the actual syntax
Sample code snippet for Inheritance
Actual Child Class Definition
What is the CHILD class doing ?
As we are all aware, square is just another polygon which has 4 sides. I would love to use the methods and attributes of this polygon to get the length of input sides and calculate the perimeter without repeating the code. Hence, I have inherited the information from ‘polygon’ class into the ‘square’ class.
Notice, the area estimation class is a newly defined class that is added to the CHILD class. Area formulations are different for different shapes, remember ??
This area estimation class does not explicitly initialize new variables for the number of sides, length of each side and the perimeter. All we do is just initialize the PARENT polygon class from within the CHILD class using super().
Let us see, if the story I told holds good or not !!
‘In the expression below, ‘4’ argument which gets passed into the polygon.__init__() through the super().__init__()
Congratulations, SIMPLE INHERITANCE has been successfully implemented
The complete code is available @ GitHub