There are, of course, disadvantages to composition. It requires more code than inheritance, as we saw, Ortiz said. It is often more difficult to read the code using composition than it is to read code using inheritance.
I think this is the main disadvantage, at least in languages like C++ and Java; if you want to be dogmatic about the OOP-ism of encapsulation and that stuff, all those "methods that just call another method on the composed sub-object" create lots of bloat that a compiler may or may not be smart enough to inline, but a human certainly would have to deal with --- and that adds overhead when debugging and otherwise maintaining the code. Speaking as someone who really hates such "useless" code, composition (especially sometimes of the nested variety) can get annoying really really quickly ---needing to "thread the call" to the right place through many composed objects just feels more like busywork than accomplishing anything functionally useful. If you inherit, you automatically get the union of the methods (and only when there's name collisions do you need to disambiguate), but inherit too deeply or widely and it gets more difficult to find where the code is.
Of course, none of this is relevant at all to the code I normally write using C, where there is no inheritance and everything is composition, and not being an "OOP purist", I'm perfectly happy with BAR_dosomething(&foo.bar);
>needing to "thread the call" to the right place through many composed objects just feels more like busywork than accomplishing anything functionally useful
Doing this is a pretty strong code smell. If you have chains of object references that need to know about the internal structure of other objects, perhaps think about the Law of Demeter? https://en.m.wikipedia.org/wiki/Law_of_Demeter
That's exactly the problem with being dogmatic about OO --- even the page you linked to mentions it:
Although the LoD increases the adaptiveness of a software system, it may result in having to write many wrapper methods to propagate calls to components; in some cases, this can add noticeable time and space overhead
Suppose foo() inside class X needs an extra parameter or similar, but that parameter actually needs to come from A which contains an instance of B which contains a C which contains a ... ... which contains the X. Instead of changing only foo() and the b.c....foo() in A, being dogmatic means having to change all the do-nothing wrapper methods on that call chain.
If anything, I'd say wrappers are the real code smell. You can probably tell I'm not a fan of OO; I've encountered the aforementioned situation countless times, where the real purposeful change takes a tiny fraction of the time compared to going through all that other do-nothing code and changing it too. The mind-numbing depth of indirection and wasteful bureaucracy is excruciating.
Can you give a brief example of the situation you are describing? Or a link to an article on this?
I am really interested in improving my coding using functional programming, composition, etc... but so far, I haven't been able to understand the benefits in my current circumstances. (I've done a lot of reading already) I am hoping I will run into one, so I can see clearly why it's worth the effort to implement. (ie, implement something new when upgrading/replacing some old OOP code...)
In my example x was a contained object, and y, z, w were member variables or methods on that object. A shorthand for wrappers was exactly what I intended.
I think this is the main disadvantage, at least in languages like C++ and Java; if you want to be dogmatic about the OOP-ism of encapsulation and that stuff, all those "methods that just call another method on the composed sub-object" create lots of bloat that a compiler may or may not be smart enough to inline, but a human certainly would have to deal with --- and that adds overhead when debugging and otherwise maintaining the code. Speaking as someone who really hates such "useless" code, composition (especially sometimes of the nested variety) can get annoying really really quickly ---needing to "thread the call" to the right place through many composed objects just feels more like busywork than accomplishing anything functionally useful. If you inherit, you automatically get the union of the methods (and only when there's name collisions do you need to disambiguate), but inherit too deeply or widely and it gets more difficult to find where the code is.
Of course, none of this is relevant at all to the code I normally write using C, where there is no inheritance and everything is composition, and not being an "OOP purist", I'm perfectly happy with BAR_dosomething(&foo.bar);