1
$\begingroup$

In discussions about why most languages which implement inheritance only implement single-inheritance, the question of the precise semantics of overlaps often comes up, and having redundant data members is sometimes given as an example semantic that would be undesirable. Note that this semantic effectively implements inheritance with composition.

Given that "prefer composition over inheritance" seems to be the current prevailing wisdom, having overlaps be redundant doesn't sound as bad as it once did.

So my question is:

Are there any programming languages which implemented multiple inheritance by adding redundant data members? How did that turn out, if so?

$\endgroup$
4
$\begingroup$

It does not matter how you implement multiple inheritance, the inherent issues coming from that still apply.

If $C$ is a class, and $D$ a derived class (subclass), and $d:D$ we can write d.foo() to call a method that can be defined in $D$ (possibly ovverriding $C$'s own method) or the method which is inherited from $C$ (and not overridden). In any case, there a clear choice on which one should be called.

If instead $D$ derives from $C_1,C_2$ then that method might be inherited from both and we need to disambiguate somehow. For instance, d.foo() could be an error now, and we could require something like d.C1::foo() instead. Or we could give priority to the "first" superclass. Or we could require that the definition of $D$ must resolve the ambiguity (e.g. an overridden method is now mandatory). None of this is an ideal solution. Liskov substitution principle for $C_2$ is likely broken by any of these options.

Using composition instead of inheritance, things hardly change. We still need to disambiguate. We can use d.field_c1.foo() instead. We can make $D$ to define a foo() method that chooses according to the wanted priority. We also have the additional option of making $D$ not expose the foo() method at all, but this means that $D$ can no longer be considered a subtype of $C_1,C_2$, not even in some lax sense.

More pragmatically, after decades of being almost dogmatic about OOP, the software engineering community is now coming to a more honest evaluation of it, trying to highlight the advantages without hiding the issues. Inheritance is now still found interesting and useful, but much less so.

$\endgroup$
  • $\begingroup$ I'm presuming your answer to my question about whether anyone tried implementing inheritance with composition is "probably not." with the post serving to explain why. If so, then this certainly answers my question. $\endgroup$ – Ryan1729 Oct 16 '17 at 6:36
  • $\begingroup$ @Ryan1729 It depends on what you mean with "implementation". In C++, I think the memory layout of composition vs multiple inheritance is pretty much the same. So, if you want, the latter is implemented as the former, plus allowing the subtyping (ancd some smart casts). The programmer has to resolve the inherent ambiguities in some way, though, in both cases. $\endgroup$ – chi Oct 16 '17 at 8:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.