4 ms·
For me, what really made it click and think about how different it is from class-based inheritance was an old Steve Yegge post: http://steve-yegge.blogspot.com/
by Stwerner 7y ago
For me, what really made it click and think about how different it is from class-based inheritance was an old Steve Yegge post: http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html http://steve-yegge.blogspot.com/2008/10/universal-design-pat...
It is a really long post and heavily references Godel, Escher, Bach but this section I think explains the difference really well:
Hofstadter offers several supporting examples for this thesis, but I'll paraphrase one of my all-time favorites. It goes more or less as follows.
Imagine you're listening to announcers commenting on an NFL (American football) game. They're talking about a new rookie player that you don't know anything about. At this point, the rookie – let's say his name is L.T. – is just an instance of the class "football player" with no differentiation.
The announcers mention that L.T. is a running back: a bit like Emmitt Smith in that he has great speed and balance, and he's great at finding holes in the defense.
At this point, L.T. is basically an "instance" of (or a clone of) Emmitt Smith: he just inherited all of Emmitt's properties, at least the ones that you're familiar with.
Then the announcers add that L.T. is also great at catching the ball, so he's sometimes used as a wide receiver. Oh, and he wears a visor. And he runs like Walter Payton. And so on.
As the announcers add distinguishing attributes, L.T. the Rookie gradually takes shape as a particular entity that relies less and less on the parent class of "football player". He's become a very, very specific football player.
But here's the rub: even though he's a specific instance, you can now use him as a class! If Joe the Rookie comes along next season, the announcers might say: "Joe's a lot like L.T.", and just like that, Joe has inherited all of L.T.'s properties, each of which can be overridden to turn Joe into his own specific, unique instance of a football player.
This is called prototype-based modeling: Emmitt Smith was a prototype for L.T., and L.T. became a prototype for Joe, who in turn can serve as the prototype for someone else.
- nerdponx 7y agoThat's a helpful explanation. How would a type system work in that context? Or is there no such thing?
- Stwerner 7y agoHah that's a good question. I haven't really thought about that or explored type systems that would interact with this pattern. Would be really interested in reading about it though!
- nerdponx 7y agoIt seems like the answer is "not well, and it's not recommended": https://softwareengineering.stackexchange.com/questions/95126/how-does-a-static-type-system-affect-the-design-of-a-prototype-based-language https://softwareengineering.stackexchange.com/questions/9512...
- jolmg 7y agoIt's not just about static type systems, though. nerdponx was asking about type systems in general. It's a tricky question even for dynamic type systems. Javascript keeps reference to the constructor and the prototype, so you can determine the "type" that way, but that's not the only way a prototype-based OOP language can work. A language can work without keeping such references and instead simply copying each property on cloning. How do you determine the type of an object then? Is the type based on the presence of certain properties? Does it include the equality of the values of such properties or does just their presence suffice? Does having additional properties change the type? There seem to be many questions with arbitrary answers in making such a dynamic type system.
- nerdponx 7y agoI made both comments! I think I had static type systems in mind when I asked the question, but that was helpful all the same. It seems in the case of Self it does in fact keep the reference around. I suppose the whole point of a static type system is moot with a fully prototype-based language. Instead maybe you can enforce compile-time checks (contracts?) on the messages an object is expected to receive.
- jolmg 7y ago> I made both comments! Ha! I did not notice! XP > I suppose the whole point of a static type system is moot with a fully prototype-based language. Instead maybe you can enforce compile-time checks (contracts?) on the messages an object is expected to receive. I think if you can do the latter, you can probably do the former. By that I mean you can probably do neither. If cloning is something you do in runtime, how can you enforce compile-time checks on the messages they're supposed to receive? Such messages are defined at runtime.
- thelazydogsback 7y agoThese are really different facets of the same rookie and have to do with the role he can play in various relations -- each facet can come from a different prototype (or class...) if necessary. So "viewed as a" or "in the role of" a Catcher, we "see" certain attributes, and "as a runner" we see others. Certain knowledge representation schemes (frame systems, description logics, default reasoning and truth-maintenance schemes, etc.) can deal with this context-sensitivity well -- programming languages tend to have some weakened notion of these things, such as Inferfaces or Traits.