3 ms·
> Honestly I've not seen such a strong characterization of inheritance as being purely semantic. As articulated elsewhere in the discussion, classical inherita
by rectang 6y ago
> Honestly I've not seen such a strong characterization of inheritance as being purely semantic.
As articulated elsewhere in the discussion, classical inheritance has a great affinity for the "specialization" design pattern, which is everywhere. Classical inheritance is not just a performance hack, it is semantically compelling, as illustrated by the enduring popularity of "Cat Extends Animal"!
Furthermore, single inheritance has a really elegant canonical implementation: "extending" structs and vtables in subclasses by appending their member variables and new virtual method pointers.
Using composition may inoculate against certain brittleness problems in code sharing, but if "has-a" is cumbersome to code up, no amount of scolding is going to change mass behavior.
Emphasizing interface inheritance as an alternative to classical inheritance seems to be more effective at breaking people away from the problems of implementation inheritance, even though interface inheritance is still "is-a" and not "has-a". And "fat pointers" with two words, one for the dispatch table and one for the object, are an elegant canonical implementation for interface inheritance.
> Sure, there's the "Cat extends Animal" shtick that refuses to die. But everyone refers to this kind of talk of inheritance ironically these days.
This sort of "everyone knows" dissing of inheritance is why I tend to dislike HN discussions of it.
For what it's worth, the rust-by-example for traits uses the Animal "schtick" unironically:
https://doc.rust-lang.org/rust-by-example/trait.html https://doc.rust-lang.org/rust-by-example/trait.html
- Twisol 6y ago> Classical inheritance is not just a performance hack, it is semantically compelling I think often it's compelling for misleading reasons. For example, is a square a rectangle? Mathematically, yes. But in mathematics, we don't mutate values (we would describe an entity's evolution as a series of values). If you are allowed to mutate the dimensions of a rectangle object, then for a square to be a rectangle, it must set both dimensions when setting either, or otherwise cause an error if its dimensions get out of sync. If you can, say, get the area of a rectangle, Liskov's principle of behavioral subtyping suggests that such a square would break the expectations of a client of rectangles ("I changed the width but now I'm getting the wrong area!"), so a square is not really a rectangle. You may recover behavioral subtyping if you explicitly limit the kinds of reasonable inferences a client can make from a rectangle, but that may limit your use cases for actual rectangles. I like this phrasing from one of the answers to this SO question [0]: > The problem is that what is being described is really not a "type" but an cumulative emergent property. > All you really have is a quadrilateral and that both "squareness" and "rectangleness" are just emergent artifacts derived from properties of the angles and sides. Put differently, it's very tempting to treat "square" as a specialization of "rectangle", but that has very little to do with their intrinsic definitions and far more to do with what can be observed of them by the program in context. [0] https://stackoverflow.com/a/1030559/159876 https://stackoverflow.com/a/1030559/159876
- lupire 6y agoThat's cleared up by understanding covariance and contravariance and the fact that mutability is an attribute.