In two of my previous posts, I shared my understanding about two key pillars of object orientated  programming - Abstraction and Encapsulation and how to apply those concepts in building a robust Test Automation framework. Incase you have missed reading it, here are the links:

In continuation to the journey of learning oops concept and applying those in real time, lets deep drive into the another important pillar of object oriented programming in this post. You are getting me right, we are going to understand about Inheritance detail with some real time examples.

Before we get started, here is a quick overview of what the readers can expect to take away from this post:

- What is Inheritance?

- What are the different types of inheritance ?

- How to implement inheritance?

- What are the benefits of inheritance?

- What are the pitfalls of inheritance?

- How can we use inheritance in a test automation framework?

What is Inheritance?
As the name implies, inheritance is a mechanism of creating new classes using the classes that has already been defined. From this definition, we may think that the primary purpose of inheritance is to reuse code but which is not always true. We will come to this point again in later part of the post after getting some more understanding about inheritance. 

Why do we need inheritance?
To achieve categorisation
- Inheritance helps to group objects into categories for a specific purpose. For example a car, bus, truck can be categorised as a  type vehicle where each of those are unique but still have common properties of vehicle like having wheels that supports rotation in left and right direction. It gives a clear understanding of the object and differences based on the categories.

To achieve modularity
-Modularity is the process of decomposing a program into a set of modules so as to reduce the overall complexity of the problem. Inheritance supports modularity by allowing us to create smaller sub classes where each sub class is solving some unique problem. For example we have a parent calculator class and we have two child classes performing basic and scientific calculations.  

To achieve clear representation of concepts and separation of concerns
Separation of concern means focusing on one thing at a time. There are two rules that can help to identify the concerns of a software component:
- The reason of change
- The frequency of change

Using inheritance we can build a hierarchy of concepts separated in concerns at different level of abstraction. For example let's consider that we need to build a laptop. The different components, we may need to build a laptop may have different lifetime and reason for changing the same will also vary depending upon the type. For example hard disk, battery and motherboard can have its own areas of concern. 

Separating components based on the representation of concepts and areas of concerns can help in various ways like:
- Classes can be changed frequently based on the need without effecting the others.
- Classes can be changed for different reasons without effecting the others.


Example from Test Automation Framework:
We can observe the above benefits in a typical web automation framework where we create page classes to mimic the real world  web pages. 
- We create a base page class and derive all the child page object classes from that.
- Each page class can have its own responsibility and reason for change.
- Each page class can reuse base class's common properties/methods.


Types of Inheritance
Implementation inheritance (class inheritance)
- When we create a sub class, we are actually extending the parent class's functionality by inheriting the properties/methods implemented in the parent class. Code reuse and modularity are the benefits of implementation inheritance. But in the other side of the coin, in this approach the sub class will be tightly coupled with the parent class. So any change in the parent class may need the understanding of all the sub classes to avoid breaking them.
Example: Page classes derived from base page class.
 
Interface inheritance (type inheritance)
- Instead of directly inheriting from a class we can also inherit from interface by implementing the methods defined in the interface. This will help in removing the tight coupling between parent and child classes. Each child class can have its own implementation which may be similar but not same as the other classes. But care should be taken not to break the inherited classes by changing the interfaces or forcing the classes to implement a method which it does not need. We cannot achieve direct code reuse here, since interface can only define methods but does not provide implementation. 
Example: Driver interface with with browser specific implementation classes

How to achieve code reuse using inheritance?
Using Implementation inheritance i.e having Is-a or Is-an relationship between base and subtype. For example - SavingAccount is a type of Account and CurrentAccount is also a type of Account. Both SavingAccount and CurrentAccount share same intent of base class Account and they extend the behaviour of  Account with additional capabilities. In this case code reuse is obvious along with modularity. But if we want to create another subclass LoanAccount this may violate Liskov substitution principle because the intent of LoanAccount is different if we consider interest calculation as a major operation as compared to SavingAccount and CurrentAccount. In the similar way, page object classes shares is-a relationship with page base class (reference web automation framework). This enables code reuse since page object classes inherits common properties/methods from the base page class.  But this has some limitations as well, just consider the situation when new web pages are getting added to the application, we also need to add new page classes to the automation framework which may be a difficult to manage and maintain in long run. This may increase the number of classes significantly. 

Using Composition i.e having "has-a/has-an" relationship between two classes. Let's consider the page object example again here. 


In the above simple web page layout, we can actually logically sub divide the same into different component like Header, Left Panel, Right Panel, Middle Panel, Footer etc. We can pick up each component and further sub divide those into smaller components if applicable for example Header can be sub divided into Banner, Logo, Contact, Title, Search which will be present in each an every page we encounter in that application. So instead of using direct is-a relationship, in this case we can consider has-a/has-an relationship between the classes. For example, page has a header component, page has a footer component etc. This approach will help to reuse code when pages contains similar components. Here is the code representation of this process using a demo website http://automationpractice.com/.


What are the pitfalls of inheritance?
-Tight binding between base class and its sub class.
-Makes code difficult to change.
-Relationship cannot be changed at run time.
    In this article, I have discussed both pros and cons of using inheritance with examples. Hope this will help to come up with better design decision next time you are encountering any problem which can be solved using inheritance. Feel free to share your thoughts and comments in the same line.