Inheritance was invented as a performance hack
After reading all the comments of many confused and curious, here is when inheritance is bad and why so _in the absence of any performance considerations_.<p>First, inheritance from an interface&#x2F;trait is totally okay. The problem is class inheritance, meaning implementation inheritance.<p>There are two cases:<p>1) you inherit from a class and only add methods but don&#x27;t overwrite anything. This is the good case, you can do that<p>2) you inherit from a class and overwrite one ore more of its methods. This is the bad case, no matter how you look at it. And here is why.<p>Look at the following classical simple Stack class:<p><pre><code>    class Stack(...) {
       def push(element) returns nothing = ...

       def pushAll(elementlist) returns nothing = ...
       
       def pop() returns element = ...
    }
</code></pre>
Now imagine you want to keep a count of the number of elements, so you decide to extend the class:<p><pre><code>    class CountingStack(...) extends Stack {
       override def push(element) returns nothing =
           count += 1; super.push(element)

       override def pushAll(elementlist) returns nothing =
           count += elementlist.size; super.pushAll(elementlist)
       
       override def pop() returns element =
           count -= 1; super.pop(element)
    }
</code></pre>
Looks good no? Can you spot the problem?<p>If the Stack class implements pushAll as iterating over the elementlist and calling push for each element, then the CountingStack will count twice!<p>We could try to just not overwrite pushAll in CountingStack - but what if the Stack class is later changed to implement pushAll without calling push? Then CountingStack would now miss counts.<p>This problem is impossible to fix and it is a general problem - when overwriting a method, you can never be sure that semantics could break when the base class is changed.<p>So what is the solution here? Simple: use composition over inheritance.<p><pre><code>    class CountingStack(underlyingStack) {
       def push(element) returns nothing =
           count += 1; underlyingStack.push(element)
     
       override def pushAll(elementlist) returns nothing =
           count += elementlist.size; underlyingStack.pushAll(elementlist)
       
       override def pop() returns element =
           count -= 1; underlyingStack.pop(element)
    }
</code></pre>
Problem solved - no matter how Stack is implemented, our CountableStack will always be correct. The drawback (if you want to call it one) is that we need some common interface&#x2F;trait that both Stack and CountableStack will implement.<p>I hope that sheds some additional light on why (implementation) inheritance is often considered a bad practice.