Diamond problem
|
In object-oriented programming languages with multiple inheritance, the diamond problem is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If a method in D calls a method defined in A, which class does it inherit from, B or C?
Missing image
Diamond.png
Image:diamond.png
It is called the 'diamond' problem because of the shape of the class inheritance diagram in this situation. Class A is at the top, both B and C separately beneath it, and D joins the two together at the bottom to form a diamond shape.
Different programming languages have addressed this problem in different ways:
- In some languages, it is not possible to inherit from the same class twice. Java only allows the multiple inheritance of interfaces, which never have any methods implemented in them.
- C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" ("class B : virtual A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A.
- Eiffel handles this situation by a select and rename directives, where the ancestors' methods to use in a descentant are explicitly specified. This allows to share the methods of the base class between its descentants or even to give each of them a separate copy of the base class.
- Perl handles this by specifying the inheritance classes as an ordered list. In the above ambiguity, class B and its ancestors would be checked before class C and its ancestors, so the method in A would be inherited through B.
- Python had to deal with this upon the introduction of new-style classes, all of which have a common ancestor,
object
. Python creates a list of the classes that would be searched in left-first depth-first order (D, B, A, C, A) and then removes all but the last occurrence of any repeated classes. Thus, the method resolution order is: D, B, C, A.
The diamond problem is not limited to inheritance. It also seems to arise when header files A, B, C, and D "#include" one another in a diamond as above and separate precompiled headers are created from B and C. If these two precombined headers are combined, declarations in A are duplicated; the "#ifndef" convention (see Header_file) is ineffective.