Python language basics 81: polymorphism through inheritance

In the previous post we looked at interface polymorphism in Python. In fact there are no explicit interfaces in Python like in Java so I simply made up the term “interface polymorphism” referring to strictly typed languages.

We saw an example of two methods: one that printed the provided data in XML format, and another which performed the same in JSON format. The print_as_xml and print_as_json functions, which are also objects, implicitly implemented an interface with one method. This method is void, i.e. has no return type, and accepts two input parameters: a root name and the properties to be printed arranged in a dictionary. The Person object then had a format_me method which accepted a formatter and delegated the actual formatting implementation details to the mechanism that was passed into it. It’s important to keep in mind that the Person object remained oblivious of these implementation details and didn’t need to concern itself with the rules concerning JSON, XML, etc. Also if we pass in a function that doesn’t adhere to the implicit interface then an exception is thrown.

In this post we’ll start looking into another key idea in object-oriented design: inheritance. We’ll start with some theory and key terms. The upcoming posts will show the ideas in action.

“In object-oriented programming, inheritance is when an object or class is based on another object (prototypal inheritance) or class (class-based inheritance), using the same implementation (inheriting from an object or class) specifying implementation to maintain the same behavior (realizing an interface; inheriting behavior). It is a mechanism for code reuse and to allow independent extensions of the original software via public classes and interfaces. The relationships of objects or classes through inheritance give rise to a hierarchy.”

To receive as one’s portion; come into possession of: to inherit his brother’s old clothes.

To receive qualities, powers, duties, etc.,

To receive as if by succession from predecessors: the problems the new government inherited from its predecessors.

Inherit has a number of other meanings but I thought that the above definitions match the object-oriented sense the closest.

Inheritance in programming

The verb “receive” is a common feature across the listed definitions: an object receives something from another object. This “something” is most often a function and/or a constructor. The “another object” will be something like the predecessor referred to by the third definition on the list above. In programming the predecessor object is often called a base class or superclass or also an abstract class. The object that receives the functionality from the abstract/super/base class is called the derived class or subclass or even a concrete class.

Base classes cannot be used on their own as they lack the full implementation details of one or more functions. They can still be instantiated but if you try to call one of its functions with missing implementation details then an exception will be thrown. These implementation details are then defined within the derived classes.

At the same time the base classes can have functionality that the derived classes all have access to and can use during execution time. It is a means of code re-use in order to avoid duplication.

We’ll continue with some initial examples in the next post. You’ll see that while the theory and terms like “abstract class” may sound intimidating, they are quite straightforward in practice.