No, it allows you to use them. No inheritance is taking place, however the larger point is that "use" of an object provides all the same benefits of inheriting it.Jonah Bron wrote:So you're saying it's good because it allows an object to "inherit" multiple objects?
And yes Vlad is right inheritance tackles a larger problem. But when you dependency inject (use composition) that problem vanishes, and inheritance is not needed as much. Once you start using interfaces its technically not needed at all.
Take your classic Cat vs Dog example. Both historically extending Animal. Well in a more modern program, both would implement Animal, not extend it. Instead of there being a walk() method on the Animal class, there would be no animal class. Instead, both Dog & Cat have a walk() method that delegates to a "walking strategy" (the strategy each animal should use would be configured thru a setting, passed to the constructor or set from some database or config file).
We no longer need an animal class, just an animal interface. Now we can use that walk() method on non-animals, namely killer robots where we don't need a breathe(), eat(), drink(), or sleep() unwanted methods that would come from having robot extend animal. WIth inheritance you only wanted the walk() method but you took a bunch of extra methods you didn't want too. With composition you can take what is needed. Also there's animals that don't walk. Inheritance fails at modeling the real world I live in.
Sure you could put the walk() method in a class WalkingAnimal that extends Animal, and have your Cat class extend that. But you're already making an explosion of classes for no reason, and I haven't even given you a difficult requirement
With interfaces & composition, there is no more diamond problem. Your dog implements "breathing", & "walking". Your killer-robot implements "killing", & "walking". You use composition (strategy pattern in this case) so that both dogs & robots can walk, without having to copy paste (except for 1 line method that delegates to the walking strategy)*. Not only does this solve the diamond problem but it will promote better practice. You can break up your logic for walking within it's own walking class now. It follows the single responsibility principle in a simple or complex program, whereas inheritance you eventually end up breaking the single responsibility principle, or duplicating code, or having excess methods that aren't needed in a particular sub-class)
* only prototypical inheritance "solves" this as far as I know, but I don't see it as a thing to solve. I see it as a place to put security checks, etc.
With all this being said, inheritance may be more elegant in certain situations. But if you code from a business perspective, factor in unknown user requests, etc.. composition provides more benefit & less business risk. Objects in real life don't exist in a hierarchy, its a flawed way of looking at the world and there will eventually be a wrench in your gears some day for some user request.