I think one of the biggest reasons why most libraries/frameworks/apps/etc. use inheritance over composition is the easy with which the underlying languages allow the use of inheritance as opposed to composition. Most of these software writers know SOLID and other OO principles but when they're faced with the actual implementation, inheritance is just too damned easy to implement.
There are lots of relatively coherent arguments already floating around the interweb around why composition is generally preferable to inheritance when it comes to code reuse; lots of people have strong feelings both ways.
I should point out, however, that many OO languages (like Java and C++) make inheritance much easier than composition, and as such inheritance seems more useful than it actually is, simply because it's all you've got. In languages that have better syntactic support for delegation and other compositional techniques, the usefulness of inheritance is significantly lessened. In other words, the usefulness of inheritance is more accidental (i.e. because you often don't have other good options) rather than inherent (i.e. because there simply aren't better options that are possible or available in other languages).
I think the reason people prefer inheritance is because it gives them the illusion that their code is simpler. They don't see the huge interfaces implied by inheritance because they are implicit.
Composition, on the other hand, is explicit. When you use it, you notice the complexities. That gives you an incentive to simplify your design, which makes you write actually simpler code.
Inheritance makes some sense, but composition is much, much easier to understand and work with. Inheritance has well documented problems that composition does not. It’s not so much about being object oriented or not, at least not directly.
I could elaborate, but others have said it better anyways.
Inheritance is a conceptually more complex issue that isn't just about code reuse and doing things slightly differently than a parent. Composition doesn't make such assumptions. It only assumes that the parts conform with some interface.
I see pretty much the same problem with JavaScript. It's everywhere -- framework developers are busily implementing polymorphism, inheritence etc. all over the place. Yet I can't recall ever choosing to use "inheritance" instead of composition in my JavaScript projects.
Perhaps an issue is that the well known saying "prefer object composition over class inheritance" isn't done, because a majority of programmers simply don't know how to apply it.
Inheritance is used inappropriately (outside of frameworks) almost everywhere.
This criticism against OO programming is more of a criticism against junior-level OO programming. A lot of beginning OO programmers go crazy with complicated object models that aren't necessary. Composition is often a better way to go than inheritance.
To be honest I use composition over inheritance because it fits better with my mental patterns. I've nothing against OOP in general and I'm pretty sure we can have code with good performance also without a component-based model. The fact is just that I'm not as good at designing things with OOP in mind as I'm when I design them with components in mind. But this is me, not a golden rule.
The problem with inheritance is that no one seems to know where to use it best. Everyone just goes by feel and feelings frequently turn out to be wrong.
Composition is nice because it’s very simple and we can understand it mathematically. If you’re trying to understand inheritance mathematically then you’re basically left with using it only for algebraic structures (groups and rings and fields and vector spaces). But then you don’t really need inheritance there if you just have plain types and operator overloading.
Looking at that article, it seems nearly every complaint is about inheritance. But it is quite possible to use objects with composition. In fact, I think 'composition over inheritance' has been a commmonplace since the late 1990s.
We forget that favoring composition over inheritance is one of the core ideas of OOP. It's supposed to be, at least.
Textbooks have an example like "Dog inherits from Animal" as a way to demonstrate the concept of inheritance, but people took that as an invitation to become Linnaeus and create a hierarchical taxonomy of their domain.
It might be a useful exercise, actually, but it's rarely the best way to design software and you can do OOP (and do it better) with sparing use of inheritance (by replacing it with extensive use of composition).
I think the real takeaway is that composition is much more likely to model the semantics you have, even though inheritance feels like it gives you better code re-use.
Composition over inheritance solves only certain language problems where limitations of expressive power make the code less transparent or flexible, but it’s not a solution for decomposition. The problems with properly used inheritance arise only in sufficiently old and evolved code, because decomposition of one domain does not necessarily describe well another (evolved) domain. Programmers tend to think that every problem in the world should be addressed by better coding, so they try to change their coding practices. In fact, solution here is managerial - throw away the old code and do the decomposition once again, for the new circumstances and new requirements. OOD and inheritance work well, so let’s not blame them for the use cases which they cannot solve.
Its the fragility of large inheritance hierarchies. They work well for very rigidly defined real world structures but not so well in most real-world usages.
reply