Learn inheritance by applying it in a practical scenario.
Learn inheritance by applying it in a practical scenario.
Inheritance is the concept of using the functionality offered by another class and building on top of it. This way, multiple new classes can build upon one class which is offering the base functionality, thus re-using code to avoid duplication.
In this Byte, we will see how Inheritance can be a good design principle and where to apply it.
Understand how inheritance can lead to better software design
Learn where it can be applied
Learn inheritance by applying it in a practical scenario.
Inheritance is the concept of using the functionality offered by another class and building on top of it. This way, multiple new classes can build upon one class which is offering the base functionality, thus re-using code to avoid duplication.
In this Byte, we will see how Inheritance can be a good design principle and where to apply it.
Understand how inheritance can lead to better software design
Learn where it can be applied
You can download the source code from gitlab by executing one of the following commands:
git clone https://gitlab.crio.do/crio_bytes/me_inheritance.git
git clone git@gitlab.crio.do:crio_bytes/me_inheritance.git
If you don’t have Git already installed. Use this as a reference to help yourselves do that.
Execute this command in terminal to download the dependencies
pip3 install -r requirements.txt
Verify by running the single_class_proposal/main.py file
python3 single_class_proposal/main.py
Our company was one of the first to support Text Messaging through an App. However, in recent years, with the advent of more advanced Messaging apps like Whatsapp, Viber etc., it isn’t able to attract new users.
With plans to regain lost ground, the company wants to revamp its code and start adding support for other kinds of media.
Let’s look at the current code base. Look at the files in the outermost directory of the git repo you have cloned. The focus is on the Message
class object, which is passed between multiple methods to make the messaging happen. The class contains all data fields that are relevant to the text message.
The Message
class is defined in message.py.
It has fields like __sender
, __receiver
& __message_content
.
It has methods to access these data fields from outside the class. There are getters (methods to read value of fields) & setters (methods to write values of fields) for the above fields. This shows it has been designed with Encapsulation in mind.
Note: The field names with leading double underscores is how we say it’s restricted for direct access from outside the class. This is because Python doesn’t support "private" fields/methods by default.
We have methods inside android_client_handler.py that implement the functionality to send messages making use of the Message
class.
send_message(message: Message)
- method that wraps the other methods below to process & send the message. This will be invoked by the android client (simulated by main.py here).
check_for_offensive_content(content: str)
- method to check the message to be sent for offensive content and takes in as argument a string (str
)
store_message(message: Message)
- method that stores the message info for later use and requires a Message
object as argument
deliver_message_to_receiver(message: Message)
- method which handles the actual message sending to the receiver
Let’s do a simple demo of our app now by using the methods available. We have some code in main.py that does this
# create an object of the Message class
message_1 = Message()
# use the Message class setter to set the sender
message_1.set_sender('SENDER_Amar')
# use the Message class setter to set the receiver
message_1.set_receiver('RECEIVER_Abhinaya')
# use the Message class setter to set the message content
message_1.set_message_content('Hello, Have you checked out https://blog.crio.do?')
# use method provided by android_client_handler.py to send the message
send_message(message_1)
Wanna try running main.py? Execute the below command
python3 main.py
In order to start enhancing the App, the first set of requirements are listed below.
Add support for
Voice message
Image message
The fields and methods required for each Message Type is listed in the table below.
Note: This doesn’t show the full list of messages. It shows a subset that is sufficient for the current topic.
The technical architect has now requested the team members to brainstorm and come up with design options and their drawbacks.
Yes, this situation is just right for Inheritance.
The definition of inheritance is that the parent/base class holds the common fields and methods, while the child classes get to inherit the parent’s fields and methods and add their own on top of it.
That way each child class (representing one message type) remains independent of other child classes.
This implementation is available inside the oop_way directory.
Inside oop_way/message.py, we use a Message
parent class to define fields & their methods which are common to all types of messages. E.g. message id, sender, receiver etc.
For each of the message types, namely, Text, Image & Voice, we create new children classes TextMessage
, ImageMessage
& VoiceMessage
. These children classes inherit the Message
class and hence need only add any fields and methods specific to them.
Code reuse for common fields and methods (by inheriting parent class) as opposed to repeated code in the earlier Proposal 2.
Clean class structure for the child classes that are easily maintainable. Each message type can be modified without impacting other classes since it holds fields/methods specific to itself.
The Clients get only the fields and methods for the message type they are interested in by creating an object of the child class. This is in contrast to getting all fields by creating an object of a large single Message class, as was the case with Proposal 1 earlier.
Execute this and see the output
python3 oop_way/main.py
Pay close attention to these lines of code.
single_class_proposal/android_client_handler.py
def send_text_message(message: Message):
def send_image_message(message: Message):
oop_way/android_client_handler.py
def send_text_message(message: TextMessage):
def send_image_message(message: ImageMessage):
Note that with the Inheritance based design, the invocation of the methods need to know which exact message type to use. This is not very good.
Inheritance has helped clean up the structure from the service provider side/implementation side (message.py). We’ll see how this design can be further improved to help the caller/client side (android_client_handler.py) when we visit Polymorphism.
A new requirement has come in to add support for
How easy or difficult is it to implement this with the Inheritance based design?
Summary of Inheritance
Why is it useful? - It helps separate out common functionality and fields so that they can be reused across many other classes cleanly. Avoids code redundancy.
Where to apply? - In the code base when different objects need to share common fields and functionality.
How to apply? - Define a parent class with all shared functionalities & child classes that inherit these from the parent class
What is the drawback if we don’t use inheritance? - Code duplication, Higher maintenance cost.
Types of Inheritance - Types of Inheritance
Single inheritance
Multiple inheritance
Hierarchical inheritance
Multilevel inheritance
Hybrid inheritance
Practical Scenarios
In Java, modules extend the Standard Java Exception class to include additional functionality or information that the standard class does not provide.
Java libraries Set and List extend Collection class. Vector and ArrayList extend AbstractList which in turn extends AbstractCollection
General rules of Inheritance
A class (child class) can extend another class (parent class) by inheriting its features.
Implements the DRY (Don’t Repeat Yourself) programming principle.
Improves code reusability.
Inheritance vs Composition
Encapsulation and Abstraction vs Inheritance
Encapsulation and Abstraction are helpful to develop and maintain a big codebase.
When there are similar objects in this big codebase that share common functionality, the common functionality and fields can be separated out into a separate base class which is then inherited by child classes.
Does Python support multiple inheritance? How about Java?
What is the C++ equivalent of the Java interface?
Come up with a practical scenario where Composition is better than Inheritance.
Reduce code duplication by utilizing inheritance in your projects, when you see common functionality is needed.
Answer these interview questions
What is Inheritance?
When should you use Inheritance?
Inheritance vs Composition