C++ has plain multiple inheritance, many language designs forbid it as dangerous. But some languages like Ruby and PHP use strange syntax to do the same thing and call it mixins or traits. I heard many times that mixins/traits are harder to abuse than plain multiple inheritance.
What specifically makes them less dangerous? Is there something that isn't possible with mixins/traits but possible with C++-style multiple inheritance? Is it possible to run into the diamond problem with them?
This seems as if we were using multiple inheritance but just making excuses that those are mixins/traits so we can use them.
Best Answer
There are a number of problems with multiple inheritance when it is used with full fledged classes, but they all revolve around ambiguity.
The ambiguity shows up in a few different ways:
x
, and the derived type asks forx
, what does it get?x
variables have incongruent types, you could infer it.f
with identical signatures, and someone callsf
, which gets called?And that ignores things like dynamic dispatch, type inference, pattern matching and other things I know less about which become more challenging when the language supports multiple inheritance of full classes.
Traits or Mix-ins (or interfaces, or...) are all constructs which specifically limit a type's capabilities so that there is no ambiguity. They rarely own anything themselves. This allows the composition of types to go smoother because there's not two variables or two functions... there is a variable and a reference; a function and a signature. The compiler knows what to do.
The other common approach taken is to force the user to "build" (or mix in) their type one at a time. Instead of the base classes being equal partners in the new type, you add one type to another - overriding anything that was there (usually with optional syntax to re-name and/or re-expose the overridden bits).
Depending on the language - it generally becomes troublesome or impossible to merge implementations of functions and storage for variables from multiple base classes and expose them in the derived type.
Occasionally less severe variations will pop up based on your language, but usually no. The entire point of traits are to break that sort of ambiguity.