I recently read a book discussing multiple inheritance in Python. Python is one of the few object oriented languages that permits multiple inheritance of classes. Many other languages include workarounds for multiple inheritance. For example, Java allows for classes to implement multiple interfaces. On the other hand, PHP allows for classes to use multiple traits. This article looks at programming languages I use and how they enforce multiple inheritance or available workarounds.
In object oriented programming, inheritance is when a class takes properties and methods from another existing class. With inheritance, hierarchies of class relationships are formed. For example, class
B which inherits properties and methods from class
A forms an is-a relationship, such that
B is an
A. All the properties and methods from
A are passed along to
B. If another class
C inherits class
B, its concluded that
C is a
C is an
A. Therefore the following class hierarchy is formed:
When a class takes properties and methods from more than one existing class. For example, class
C might inherit from classes
B. This is known as 'extending multiple classes.' Most languages have specialized syntax to extend (inherit) a class. Multiple inheritance is unavailable in many languages due to its complexity and ambiguity, although certain languages such as C++ and Python enable it.
To understand the pitfalls of multiple inheritance, take the case where classes
B both have a method named
execute(). When an instance of class
execute(), is the method in
B called? This is an ambiguous situation, and determining which one is invoked often comes down to documented rules.
Some object-oriented languages I use (such as Python) permit multiple inheritance. Many others prohibit multiple inheritance but provide safer workarounds. The rest of this post looks at how different languages handle multiple inheritance, in particular the diamond problem.
Although I don't really use C++, it's the language I always think of when hearing about multiple inheritance. C++ is one of the earliest languages I know of that implements multiple inheritance. In fact, the troubles that multiple inheritance gave developers in C++ is what influenced James Gosling (the creator of Java) to omit multiple inheritance from Java1.
I'm not very good at C++, but I wrote an example of the diamond problem. The following class hierarchy relates to biological trees.
At the top is a generic
Tree class, which is extended by the
EvergreenTree classes. Finally the
BalsamFir class extends both
This code works fine except for the
type() method defined in
type() on an instance of
BalsamFir is ambiguous since it could come from either
EvergreenTree. If you try to, the code won't compile.
The following is printed to stdout when invoking the
Notice that each class constructor is called once. This isn't actually the default behavior of the diamond problem in C++. It's the result of virtual inheritance, which is implemented using the
virtual keyword on the
EvergreenTree class definitions where
Tree is extended.
If the virtual keyword is removed from these class definitions, the code doesn't even compile. What impact does the
virtual keyword have?
When a class inherits another class in C++, the subclass retains a copy of all the properties and methods in the parent class2. The subclass also contains a copy of all the properties and methods from inherited classes of the parent class. This process of copying properties and methods continues all the way up the class hierarchy.
As a result of these copies, an interesting issue forms in the diamond problem. Subclass
BalsamFir stores copies of the properties and methods in
ChristmasTree and its parent class
BalsamFir also stores copies of the properties and methods in
EvergreenTree and its parent class
Tree. Notice that
BalsamFir receives copies from
Tree twice - once from
ChristmasTree and once from
EvergreenTree. This is a source of conflict that causes errors.
The fix to this issue is virtual inheritance, which is implemented using the
virtual keyword. With virtual inheritance,
BalsamFir only receives one copy of
When writing Java, James Gosling thought the benefits of multiple inheritance were not worth the risks and complexities. Java does not support multiple inheritance of classes, instead using an interface construct to simulate multiple inheritance. When Java was first released, all methods defined in interfaces had no bodies. Instead, construction of method bodies were delegated to implementing classes.
As of Java 8, methods in interfaces can have bodies. These methods are called "default methods," and are mostly used for API backwards compatibility. I wrote an article about default methods and the diamond problem back in January. While I'll let you read that post for more insight, here is the biological tree hierarchy implemented in Java:
In Groovy you can simulate multiple inheritance just like in Java. However, Groovy introduces an additional construct called a trait, which is designed with composition in mind3. Classes implement traits, which give them additional functionality. Classes can implement multiple traits, simulating a multiple inheritance model just like Java interfaces with default methods. In the case of naming conflicts for methods in traits, the method from the last trait declared after the
implements keyword is used in the class4. You can see this rule at work in the
PHP does not allow for multiple inheritance. However, just like Groovy it has traits which can be used to simulate multiple inheritance. The biggest difference between traits in Groovy and PHP is the way naming conflicts are resolved. While Groovy picks the method from the last implemented trait in the case of a conflict, PHP throws an error. When a class uses multiple traits in PHP, method names must be unique across all traits. While this is stricter than Groovy, PHP classes that inherit multiple traits are very predictable because of this enforcement.
I commented out the
type() method in
ChristmasTree in order for the example to work.
The Swift implementation is quite unique. Swift does not support multiple inheritance, but does support protocols (equivalent to interfaces in Java, Groovy, and PHP). Swift also has extensions, which allow you to add functionality to an existing class or protocol. One restriction enforced by extensions is that names of variables and methods must be unique across all extensions for a class or protocol. Therefore I couldn't create two extensions for the
Tree protocol called
EvergreenTree that both contain a variable named
type. Here is my attempt at simulating multiple inheritance:
While slightly different than function compositions, object compositions are when an object contains other objects as properties. These other objects are used to give the enclosing object additional functionality. For example, a method invoked on the enclosing object can delegate that call to an object it contains as a property. This is a way to inherit methods and properties from objects without dealing with the languages inheritance mechanism. Here is the function composition approach:
Another option is to use mixins. Mixins pass their contents to another object. Here is the mixin approach (everything stays the same except for the
Python shares the most similarities with C++ in regards to multiple inheritance. Like C++, Python enables multiple inheritance for classes, although it does not require virtual inheritance to function. Unlike C++, the method
type() works fine in Python.
type() didn't work in C++ because it was defined in two different inherited classes. Python objects maintain a method resolution order that moves through the inherited classes in the order they are defined. As soon as it encounters the first
type() method in an inherited class, it gets invoked from that class. In the following example,
type() in class
BalsamFir always delegates to
ChristmasTree because its declared as the first superclass of
This post explored how different languages use multiple inheritance or comparable workarounds. I'll add more languages to this list as I continue to explore! All the code from this post is available on GitHub.
January 31st, 2019
C# does not support multiple inheritance in its current version (7.0). The inheritance features provided by C# are comparable to those in Java prior to Java 8. Therefore, object composition is needed to create a multiple inheritance model in C#. I demonstrate composing multiple objects on GitHub. There are proposals to implement default interface methods in C# for a future release (similar to Java's default methods)6.