Class Composition vs Inheritance in Python
To be a successful software developer, it is critical to have a firm understanding of class composition. In addition to class composition, class inheritance is equally important. In this post, we are going to define class composition and class inheritance — and look at examples of each. We'll also discuss the best situations to use each. Let's start with quick definitions of each. For even more information on Class composition vs Inheritance, checkout one of our best Python online courses. It will cover these concepts and much more.
What is Class Composition?
Class composition is when a class references another class in one of its fields. In other words, composition is a has-a relationship. As opposed to inheritance, which is an is-a relationship. We'll cover more about that shortly.
What is Class Inheritance?
Class inheritance is when a class is created as a subset of another class. The new class will have all the fields and methods of the class it inherited from — in addition to its own fields and methods. Inheritance is an is-a relationship.
Now that we have a quick and dirty definition of the two, let's walk through each of them. Both definitions are similar, but distinct differences exist. Let's start by discussing class composition in more detail.
Class Composition: A Deeper Look
It should be noted that class composition is not exclusive to Python: it's a fundamental building block of object-oriented programming. However it is widely used in Python, and any Python programmer should be familiar with the concept.
Remember that a class is created using methods and fields. Methods are procedures we would like a particular class to execute. For instance, if we had a class called Employee we would like a method called get_available_time_off to see how many days off they have left.
A field is an attribute associated with the class. In the employee example, a field would be something like "employee id" or "date of birth". I.E, some object or concept inherent to the data structure we are attempting to define. A field can be anything: a string, an integer, a decimal, or more importantly, another object. When a field is another object, then we have class composition. Below is a working example:
Notice that one of the attributes is called benefits. Remember, class composition is a has-a relationship. I.E, all employees have benefits. The benefits attribute is actually a class as well. Below is the class that makes up benefits:
As you can see, the employee class is a composition of its own fields and those in benefits. In the benefits class, we receive the title from the employee class. Based on the employee's title, we determine whether or not they will get a company car, and how many days they are apportioned. Notice that we are passing the title as a string. In a perfect world, this would be an enumeration instead.
Advantages of Composition
One of the biggest advantages of class composition is the flexibility it brings to your codebase. It allows you to loosely couple different fields so that they can be repurposed for different uses. That way, we can use the benefits class for other individuals. For example, if we wanted to create a contractor class or an hourly_employee class.
Another great advantage of composition is that the field can be changed at run time. This is something that cannot be done with inheritance. With class composition, if we wanted to change the benefits to something else during runtime, we easily can do so. Unlike inheritance, where the code would have to be rewritten. Speaking of Inheritance, let's dive into that a bit.
Class Inheritance: A Deeper Look
To turn to a different example, let's say you are the owner of a hardware store and need to represent your tool programmatically. Tools are all kind of similar after all, they all have a name, a description, and a price. In order to not reduplicate work, inheritance can be used here to make the code more organized.
First, we will create a class called tool. All different tools will inherit the properties of Tool. Remember, inheritance is an is-a relationship; a hammer is-a tool, a screwdriver is-a tool, etc. Here is an example of our tool class, which will be the superclass that all others will inherit from:
It's only 10 or so lines of code, but it will really keep our code tight and organized. Because we're running a store, we know that a tool will have a price, a name, and a description. We also know that all tools are used for something, so a method called use has been included in the superclass. Additionally, our str magic method can be shared amongst all subclasses.
Now that we have defined the super class, let's create a couple of subclasses that will inherit these fields and the use method:
In this subclass, we created a class called screwdriver that inherits from the tool. The use function doesn't do anything unless we write something specific for the given subclass, so I wrote a simple print statement. Lastly, I set the price as an instance variable to three. This is saying that all screwdriver objects will be $3. Next, let's create a hammer class:
Notice it is very similar to the screwdriver class. The main difference is that we customized the use method to be specific to a hammer. Finally, let's look at how these classes would be instantiated.
After running this main class we would see:
Advantages of Inheritance
The biggest advantage of inheritance is when you need a class that is very similar to another one, but it needs to be adjusted a little bit. Unlike class composition, this is creating a tight coupling between the parent class and the child class. Inheritance will help you adhere to one of the core principles of programming: DRY (Don't Repeat Yourself). By organizing your code intelligently using inheritance, it will be far easier to read and maintain.
Hopefully, you are beginning to understand differences between composition and inheritance. Inheritance gives us the ability to define broad characteristics for certain data structures, while composition allows us to insert classes into the fields of other classes.
The best way to truly understand the difference between the two is to practice, practice, practice. Continue to experiment with both until a firm understanding is established. Remember, if the relation is an is-a, then it is inheritance. If the relationship between the two concepts is a has-a, think class composition. Happy coding!