This article is not about how inheritance is implemented in any specific programming language. There is no coding example in this article. Here we will discuss about best practices developers should follow while using inheritance.

Most of what I am sharing here I have learnt from best of Java best practices books I have read so far ‘Effective Java’ by Joshua Bloc. If you are a Java programmer and have not already read this book, you should consider reading this book.

What is Inheritance in Object Oriented Programming?

Dictionary definition of inheritance in relation to us human beings is: receiving something such as quality, characteristic or any material possession from our predecessors or ancestors by succession or genetically.

Now if we come to object oriented programming world, which is modeled based on objects, properties, their relationships and behaviors, we find lot of similarities when it comes to inheritance.

Objects are nothing but collection of properties and behaviors. So, when we say a class is extending another class, this is nothing but the child class is inheriting properties and method implementations from its parent class.

In this article I will use Java programming language to explain the concepts. But, the principles explained here holds equally good for other object oriented programming languages as well. In Java, a class can inherit properties and behaviors from another class by extending that class.

Though it is technically possible to extend any public class; it is not at all practical for all problem domains. We will learn about that in more details in next section.

Another kind of inheritance supported in Java is through Interfaces. Interfaces define a Type in Java which is a collection of method signatures that the implementing class must follow. This is like a contract that must be met.

Different classes implementing the same interface should be easily interchangeable by the clients using them without changing any client code. When a class implements an interface, it becomes a member of that type. This is similar to us being a member of specific occupation class or ethnic group. External world would expect us to exhibit certain traits or abide by certain rules.

Some languages support multiple inheritance. They allow extending from multiple parent classes. However, java does not directly support multiple inheritance for some good reasons. But, we can emulate polymorphism by implementing multiple interfaces.

When You Should Use Inheritance?

Inheritance is normally used to increase re usability when we want to enhance the features of an existing class. We might add new properties, add new methods or override existing methods to improve implementation.

However, you must remember few points discussed here before extending a class. First and most important criteria is that the class you are extending must be designed to be extended. Why is this so important? When you extend a class you depend heavily on existing implementation of that class. So, here we have two problems to deal with.

Firstly, for a class written by third party, most of the time we don’t know about implementation details of the method we are overriding or using. We only know the contract; i.e. method arguments and return types. Yes, for open source libraries you might have access to its source code. But without proper documentation it is not easy to understand the implementation accurately.

Secondly, implementation of third party classes can change in future which it not in your control. So, your extended code may not work as expected after an update of the class you are extending even if you have not touched anything in your code.

So how do we know if a class is designed for extension? Best way to find this out is to read the documentation of the library. A class designed for extension must be documented thoroughly by the author of that class. If the documentation does not clearly specifies this then it is not advisable to extend that class.

Inheritance though very powerful, increases coupling between components which reduces code maintainability.

In popular ‘template method’ design pattern, we design a parent class implementing common processing steps in a workflow or algorithm. There are certain steps in the flow that will require different implementation for different types of problem. We have to identify common parts of the implementation and put that into parent class while adding abstract methods for the scenario specific implementation. This design pattern highly increases re usability and maintainability.

So, each requirement specific child class need to override/implement specific methods to to achieve desired end to end functionality. Parent class for such cases will be an abstract class which cannot be instantiated. So, we must extend that class and implement unimplemented methods that are designed to be overridden.

You are free to extend classes that are written by your team for which you have total control. It is also advisable to put the classes in the same package and mark the methods expected to be overridden as ‘protected’ methods.

As a rule of thumb, classes in your project that form a natural hierarchy should be modeled by using inheritance. You can get a better clarity of this by asking whether a child class ‘IS A’ parent class (e.g. tiger is an animal, apple is a fruit and mac book is a laptop).

When You Should Use Composition?

Now that we have seen when to use inheritance and when not to use, let us discuss about the alternative to using inheritance which is more suitable in most of programming scenarios.

If the relation between the child class and parent class is more of ‘HAS A’ than ‘IS A’ then there is a better way of designing such classes. We call this composition. For ‘HAS A’ relationship, we should add the parent class as a private component (property) of the child class.

If we do that, objects of child class will have a reference to parent class object. Therefore, we will be able to invoke methods on parent (third party) class to do certain processing based on API documentation of parent class and then use the output to add additional property or behavior to enhance its capability.

When using a method of a third party class, we are only expecting output as clearly specified in documentation. We are not assuming how that output is derived. We are solely depending on the contract and then adding extra bit of capability on top of that in our own class.

Please also remember to use interface of the third party class as the type of property reference instead of using the type of the class. In doing so, your code is not tied to any specific implementation and any class that implements that interface can be swapped without any impact on your code.

Conclusion

That’s all folks! I hope now you have a better understanding on when to use inheritance and when not to use. We have also learnt more robust alternative to using inheritance which is ‘Composition’ when working with third party libraries. Please let me know if this article has helped you a bit in your projects. If you want me to cover any specific articles, please let me know in comments section.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.