3 ms·
> 'L' is deeply confusing, and the difficulty in understanding it is what leads to the deep and brittle class structures above. Weird. 'L' is a very intuitive
by catnaroek 10y ago
> 'L' is deeply confusing, and the difficulty in understanding it is what leads to the deep and brittle class structures above.
Weird. 'L' is a very intuitive statement: If a property holds for all instances of a supertype, it holds for all instances of any of its subtypes. In modern terms, it could be stated as “predicates are contravariant on their arguments” [0], but the basic idea was was well understood as far back as in Ancient Greece [1].
All the issues with 'L' disappear once you properly distinguish between inheritance and subtyping [2]. As the OCaml reference manual says [3]: “Be aware that subtyping and inheritance are not related. Inheritance is a syntactic relation between classes while subtyping is a semantic relation between types.” Although OCaml has structural object types, the idea also works with nominal object types: In Java, a subclass that overrides a non-abstract method ought not to be considered a subtype of its superclass. If I told you “a zebra is kinda like a horse, except it has stripes”, could you conclude that zebras are horses?
It's amazing how effectively logic clarifies issues with programming languages.
[0] https://www.schoolofhaskell.com/user/commercial/content/covariance-contravariance https://www.schoolofhaskell.com/user/commercial/content/cova...
[1] https://en.wikipedia.org/wiki/Term_logic https://en.wikipedia.org/wiki/Term_logic
[2] http://www.cs.utexas.edu/~wcook/papers/InheritanceSubtyping90/CookPOPL90.pdf http://www.cs.utexas.edu/~wcook/papers/InheritanceSubtyping9...
[3] http://caml.inria.fr/pub/docs/manual-ocaml/objectexamples.html http://caml.inria.fr/pub/docs/manual-ocaml/objectexamples.ht...
- tunesmith 10y agoI don't see how it can be argued that 'L' is intuitive to intermediate level developers. Even for senior developers you still have to stop and think rather than trust your gut. Developers will very intuitively see the bass class as the one that handles the most common cases, and subclasses as the exceptions that "override" and vary things a little bit. My favorite example is the Doctor that can see all patients, and the Pediatrician that sees only children. Intuition would make Pediatrician the subclass of Doctor, when it should be the other way around. [1] [1] http://closuretools.blogspot.com/2012/06/subtyping-functions-without-poking-your.html http://closuretools.blogspot.com/2012/06/subtyping-functions...
- catnaroek 10y ago> Developers will very intuitively see the bass class as the one that handles the most common cases, and subclasses as the exceptions that "override" and vary things a little bit. This intuition is wrong. Java-style classes don't handle the cases you think they handle. In particular, you don't have any guarantees at all about the meaning of non-final methods, precisely because they can be overridden by subclasses anytime! They're as good as abstract, and the implementation provided is “for reference purposes only”. If you need stronger guarantees than that, then you must redefine the relationship between subclasses and subtypes as follows: (0) A subclass that mutates inherited fields isn't a subtype of its superclass. (1) A subclass that overrides inherited non-abstract methods isn't a subtype of its superclass. But the result would be a different programming language, not the Java/C#/whatever you have today. > My favorite example is the Doctor that can see all patients, and the Pediatrician that sees only children. Then either (0) it isn't true that a Doctor can see all patients, or (1) Pediatrician isn't a subtype of Doctor. If you want your types to model real life, you have to go for the former. > http://closuretools.blogspot.com/2012/06/subtyping-functions-without-poking-your.html http://closuretools.blogspot.com/2012/06/subtyping-functions... Contravariance of function arguments is intuitively obvious. I have no idea why anyone would struggle with it.
- tunesmith 10y agoLet's make sure we agree on a definition of "intuitive". I am referring to the probability that an average developer will grasp the subtyping concept and understand it instinctively once explained to the point they will easily do it correctly from that point forward. I am not referring to the inherent beauty of the concept. By that definition, my argument is that proper subtyping is counterintuitive to an average developer. Your statement that it's intuitively obvious strikes me as an opinion about the concept itself, rather than the ability of average developers to grasp it. As for the first quote of mine, yes, I agree, that intuition I described is wrong, and that is absolutely my point. It is wrong, and yet it is very common for developers to have that wrong intuition. So it is therefore not intuitive. That's why I brought it up - that (and trying to make a pediatrician a subtype of doctor) are very common areas of confusion for people trying to understand proper subtyping.