My observation is that a lot of folk misuse multiple inheritance without working through composition type questions.
The "classic" OO example of a car leads to this problem. For example, we'll say that a car breaks down to the following parts:
- it's a vehicle
- there are tires
- there is an engine
- there is a chassis
- there are seats
- and so on...
so we'll define a class that looks like this:
public class Car : Vehicle, Tires, Engine, Chassis, Seats {}
All well and good, but it presents some significant problems with encapsulation and constructors / destructors. And it doesn't accurately represent what a car looks like in the real world.
If we start asking composition questions then we'll see some nuances here that weren't at first obvious.
- is a car a vehicle? (yes)
- is a car a tire or set of tires? (no, it has a set of tires)
- is a car an engine? (no)
- is a car a seat? (no)
- etc ...
So now our class can look something like this:
public class Car : Vehicle
{
public Tires tires; //ie, myCar _has_ a set of tires.
protected Engine engine;
private Chassis chassis;
protected Seats seats;
}
Which is also all well and good. But now we start scratching our heads and say "you know, I really wish that when I instantiate a car that it has to have tires, an engine, and a chassis."
So now we can turn Tires, Engine, and Chassis into interfaces and we'll have the following class. I'm prefixing the interfaces with "I" to make the distinction more clear.
public class Car : Vehicle, ITires, IEngine, IChassis
{
protected Seats seats;
}
Interfaces are like contracts. When a class implements an interface, it's guaranteeing it will provide certain methods and behaviors.
And now things really are all well and good. Our model of the car accurately reflects the real world representation of the same Object, including some guarantees about the resemblance between the two courtesy of the Interfaces. We have avoided the icky issues that multiple inheritance can create.
That's not to say that multiple inheritance is always bad. However, it's not really needed most of the time which is why languages like Java and C# don't allow for multiple inheritance.
Importing (#import ...
) an Objective-C category adds the methods defined in that category to all instances of the class on which the category was defined. Other than with traits which can be mixed into classes selectively a category extends the class on which it was defined once and for all.
Also you can not create a standalone category and mix that into several different classes. A category is an extension for a specific class, similar as if you would add the methods to the class itself.
Traits are like java interfaces but with implementation. Wether a trait can be mixed into a class depends not on the classes name but on the methods the class provides. If a class has the methods a trait needs, the trait can be mixed into that class.
Best Answer
You're partially right: the problem exists in the case of the multiple inheritance too, but can easily be solved in some languages; diamond, on the other hand, cannot be solved that easily.
In C#, multiple inheritance is forbidden, but a class can implement multiple interfaces. Imagine that the class
Example
implementsIModifiable
andITransformable
. Those two interfaces have both a methodTransform(string) : string
. How would you implement this?This means there is no ambiguity. You have not one, but two methods with clearly distinct signatures.
Now, imagine the diamond case:
Now, when we call the method
DoSomething
onExample
, we actually want to invoke the method declared inParent
. So how would the runtime decide which one of the implementations to run?