The best way to think of inheritance is not as biological inheritance but as a contract that states … All changes of B will be made available to A, if A inherits from B. Why would anyone want such a volatile dependency and future dependent coupling ? It is insanity to program in such a way.
Alan Kay, Bjarne Stroustrup, James Gosling and all OO programmers are basically bullshitting and lying when then use examples from biology. The OO model is not based on how genes clone themselves but it is closer to the notions of land inheritance.
Prototype OO (seen in jQuery plugins) is closer to the biological model of cloning and copying. You should never use class based inheritance to model anything. Not only is it not based on reality, your code will be brittle and dependent on the whims of the base class authors. Changing the base class always guarantees code rewrites and never code reuse just like how the code is pointlessly rewritten every time a new version of React or Angular framework is released.
Sure it is problematic where misused. Perhaps the point should be that ignorance of where to apply it is evil.
To start, it should not be applied to modeling uncertain taxonomies in the problem domain. Use composition instead (if your one of the 1% that actually knows how). It should be applied in code, frameworks and libraries that want to provide the ability for users to override and extend default behavior.
Much of the blame has to be laid at the feet of those behind simple examples, useless statements and unhelpful principles. From the inapplicable dog and cat examples in books, to rote repetition of useless but authoritative sounding textbook definitions, to hand-wavy soliloquies about abstraction and modularity, to meaningless mantras about all you need to know is the “L for Liskov”.
There’s a third reason to have inheritance: ontological inheritance (the thing this class models is a special kind of the thing that class models). This is distinct from programmatic specialisation (subtyping), and can also cause problems when inheritance is overloaded to mean that in addition to subtype specialisation (which isn’t necessary in all OOP languages) or implementation sharing (which AFAIK is implied in all OOP languages but can easily be overcome).
Something feels so icky about calling Traits “inheritance of interface”… maybe it’s too much time studying biology, but traits represent characteristics a thing has, regardless of whether or not those characteristics were inherited. The concept doesn’t comment whatsoever on how the traits were acquired.
Inheritance and composition are both abstractions; abstraction is a tool for managing complexity. Complexity-management tools are good to the extent they are able to help us… manage complexity.
I hope a fair way to describe “managing complexity” is: hiding complexity in logical ways from people equipped to understand the logic and the complexity.
Dogma is not an abstraction, but it is also a tool for managing a different (even more abstract?) kind of complexity by hiding it from people because you said so.
It’s often necessary to hide complexity. Do it logically when you can and dogmatically when you must?
Inheritance can allow objects to access implementation details which should otherwise be hidden. As the article points out, mere composition cannot ever have this problem. In E, inheritance is built from composition. I don’t know whether inheritance is evil, but it’s definitely not capability-safe. This has been known for a while; in C++, friendship is used to explicitly manage this otherwise-implicit access.
I’m disappointed to not see multiple dispatch brought up, which can really change the feel of OOP.