One of the more insidious drawbacks of OOP: The tight coupling introduced by inheritance.
One of the more insidious drawbacks of OOP: The tight coupling introduced by inheritance.
The way a “real” OOP language would do subclassing, would just be composition: wrapping an instance of the “parent” and proxying messages up to it.
If such a language wanted to “support inheritance in the language” (i.e. put syntax sugar around that wrapping), the result would probably look something like Golang’s anonymous embedded struct fields — where embedding a “parent” object of type X, gives your wrapping object Y default proxy methods to call the X instance’s methods of the same name; and default proxy getters/setters for the X instance’s fields; both of which you can override as you please / are implicitly shadowed by methods+fields of the same name declared on the wrapper type.
I've not used Objective C much, but I believe the core of Objective C works the same--non-overridden methods (message handlers) of an instantiated object are invoked using the parent prototype's instance definition. Objective C derives both it's semantics and technical jargon (e.g. selectors) straight from Smalltalk. But it also supports so-called protocols, aka interfaces in other languages, which because it's a more familiar paradigm seems to be how most people associate OOP with Objective C.
I guess I'm making a hash of it, but in any event the end result is quite similar to if not largely indistinguishable from class inheritance. And because it's all dynamic, and depending on the language mechanics and your particular masochistic proclivities, it's even often quite straight forward to achieve multiple inheritance, e.g. in Smalltalk or Lua using a catch-all/fallback handler to select a method from a second (or third, fourth, etc) prototype subtree.
Additionally Self, in its original form while the Java vs Self vs Smalltalk wars were going at Sun, is a full single user workstation, only with the kernel code/JIT written in C++, everything else is Self.
It is this kind of plasticity that provided the brewing ground for high performance JITs, that eventually found their way into JavaScript, and why the usual "Python is too dynamic" excuse, is just that, an excuse for not wanting to spend the engineering resources that Smalltalk and Self JITs have trailed.
1981 "Design Principles Behind Smalltalk" Daniel H. H. Ingalls
https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk....
> After significant revisions which froze some aspects of execution semantics to gain performance (by adopting a Simula-like class inheritance model of execution), Smalltalk-76 was created. This system had a development environment featuring most of the now familiar tools, including a class library code browser/editor. Smalltalk-80 added metaclasses, to help maintain the "everything is an object" (except variables) paradigm by associating properties and behavior with individual classes, and even primitives such as integer and Boolean values (for example, to support different ways to create instances).
[pdf] https://web.archive.org/web/20230503050530/http://www.metaob...
"… since things can be done with a dynamic language that are difficult with a statically compiled one, I just decided to leave inheritance out as a feature in Smalltalk-72, knowing that we could simulate it back using Smalltalk's LISPlike flexibility. … By the time Smalltalk-76 came along, Dan Ingalls had come up with a scheme that was Simula-like in its semantics but could be incrementally changed on the fly to be in accord with our goals of close interaction." p31