Inheritance is a tool that makes a lot of sense in some situations, but that always comes at a cost. And often, the cost does not outweigh the benefit.<p>So, inheritance is not always bad, and you should not avoid it at any cost. But you should avoid it where you can. AFAIR, the original quote from the GoF book (&quot;Design Patterns&quot;) was something like: &quot;Favour composition over inheritance&quot;, not &quot;Stop using inheritance alltogether&quot;.<p>The biggest cost of inheritance (that is, inheritance of concrete methods and state) is tight coupling. You couple two classes together in a way that makes them really hard to test, change and evolve in isolation. Everything becomes worse if you have mutable state in one of the two classes.<p>This can cause ripple effects in your code: You try to fix one little defect, and in fact you end up changing several classes and unit tests because everything is so tightly coupled and because everything has side effects.<p>There are several techniques to reuse code that give you better decoupling: You can extract pure functions from your code - They are really easy and painless to reuse when you get the abstractions right. You can compose objects instead of inheriting from them. You can use callbacks or lambda expressions instead of abstract methods.<p>To recap: Inheritance always comes at a cost. And you can often find solutions that are just as easy or easier to understand, and that will better decouple and isolate parts of your code.