Earlier quoted context omitted.
I offer this thread as evidence: https://news.ycombinator.com/item?id=12342583
Hey, it's not the fault of the programming masses that some evil motherfucker conflated implementation extension (inheritance) and subtyping. Subtyping = "A Inheritance = "A inherits B, if I try to actually use it as a B, it promises to work. However, it might actually blow up in my face, because it was keeping its extra details secret from me and promising they wouldn't blow up."
Too harsh. Logic is hard for humans. Evolution has trained us to take lots of mental shortcuts, not to be perfect calculating machines. Even the most technically competent people rely on their intuition. What differentiates them from the rest of us is that they have trained their intuition to make it more reliable [0].
It's the job of a language designer to arrange things so that intuition doesn't mislead programmers regarding the meaning of language features. Before proposing a new feature, the designer must anticipate how programmers will think about code that uses this feature, and there better not be a mismatch between what programmers think the code means and what the code actually means.
> A inherits B, if I try to actually use it as a B, it promises to work.
There's nothing wrong with implementation inheritance per se [1]. It addresses a very common use case: you have a thing Foo, and you want to produce another thing Bar that's similar to Foo, with minor changes here and there. This describes accurately how many things work in real life. However, you can't assume that Bar can always be used where Foo is expected. Those “minor changes here and there” might have rendered Bar incompatible with Foo. Hence, “inheritance is not subtyping”. As stated above, it's the job of a language designer to anticipate this.
[0] https://terrytao.wordpress.com/career-advice/there%E2%80%99s...
[1] Other than the lack of mathematical elegance, but few things are mathematically elegant in life.