>discussions of OOP and inheritance often miss the influence of Knowledge Representation on OOP: I’m not entirely clear of the history myself,

Fyi... The "knowledge representation" aspect of OOP inheritance is emphasized by computer science professor Andrew P. Black. He wrote a long paper[1] about it and also has a video[2]. It's unfortunate that Black's alternative perspective (which he shared with Philip Wadler) is not discussed as often as "Object-Oriented Programming is Bad"[3] videos.

His paper is a long read (over an hour) that covers the intellectual history of OOP starting with Simula/Smalltalk. The following is an excerpt from https://www.sciencedirect.com/science/article/pii/S089054011...:

Most of us can grasp new ideas most easily if we are first introduced to one or two concrete instances, and are then shown the generalisation. To put this another way: people learn best from examples. So we might first solve a problem for , and then make the changes necessary for 4 to approach infinity. [...]

To illustrate the power of inheritance to make complex abstractions easier to understand, letʼs look at a case study from the functional programming literature. In Programming Erlang [19, Chapter 16], Armstrong introduces the OTP (Open Telecom Platform) generic server. [...]

To make sure that the message about the way that the OTP server works does sink in, Armstrong presents us with four little servers … each slightly different from the last. server1 runs some supplied code in a server, where it responds to remote requests; server2 makes each remote request an atomic transaction; server3 adds hot code swapping, and server4 provides both transactions and hot code swapping.

Each of these “four little servers” is self-contained: server4, for example, makes no reference to any of the preceding three servers.

Why does Armstrong describe the OTP sever in this way, rather than just presenting server4, which is his destination? Because he views server4 as too complicated for the reader to understand in one go. Something as complex as server4 needs to be introduced step-by-step. However, his language, lacking inheritance (and higher-order functions) does not provide a way of capturing this stepwise development.

In an effort to understand the OTP server, I coded it up in Smalltalk. [...] First I translated server1 into Smalltalk; I called it BasicServer, and it had three methods and 21 lines of code. Then I needed to test my code, so I wrote a name server plug-in for BasicServer, set up unit tests, and made them pass. In the process, as Forsythe had predicted, I gained a much clearer understanding of how Armstrongʼs server1 worked. Thus equipped, I was able to implement TransactionServer by subclassing BasicServer, and HotSwapServer by subclassing TransactionServer, bringing me to something that was equivalent to Armstrongʼs server4 in two steps, each of which added just one new concern.

Once I was done, I discussed what I had learned with Phil Wadler. Wadler has been thinking deeply, and writing, about functional programming since the 1980s; amongst other influential articles he has authored “The Essence of Functional Programming” [21] and “Comprehending Monads” [22]. His first reaction was that the Erlang version was simpler because it could be described in straight-line code with no need for inheritance. I pointed out that I could refactor the Smalltalk version to remove the inheritance, simply by copying down all of the methods from the superclasses into HotSwapServer, but that doing so would be a bad idea. Why? Because the series of three classes, each building on its superclass, explained how HotSwapServer worked in much the same way that Armstrong explained it in Chapter 16 of Programming Erlang. This was an “ah-ha moment” for Phil.

To summarise: most people understand complex ideas incrementally, by starting with a simple concrete example, and then taking a series of generalisation steps. A program that uses inheritance can explain complex behaviour incrementally, by starting with a simple class or object, and then generalising it in a series of inheritance steps. The power of inheritance is that it enables us to organise our programs incrementally, that is, in a fashion that corresponds to the way that most people think.

[1] https://www.sciencedirect.com/science/article/pii/S089054011...

[2] https://www.youtube.com/watch?v=Rmg_trKnanU

[3] https://news.ycombinator.com/item?id=19407599