> A common counterexample to OO inheritance is the relationship between a square and a rectangle. Geometrically, a square is a specialisation of a rectangle: every square is a rectangle, not every rectangle is a square. Alternatively, you can argue that a rectangle is just a square with the additional freedom to vary the width and height independently. So in C++ syntax you would have: class Square { protected: size_t…
Inheritance Often Doesn't Make Sense
61–70 of 255 posts
Re: Inheritance Often Doesn't Make Sense
#62> A common counterexample to OO inheritance is the relationship between a square and a rectangle. Geometrically, a square is a specialisation of a rectangle: every square is a rectangle, not every rectangle is a square. Alternatively, you can argue that a rectangle is just a square with the additional freedom to vary the width and height independently. So in C++ syntax you would have: class Square { protected: size_t…
> There in fact is one correct answer but people often get it wrong. You need some serious appreciation of OO to know which. Please enlighten me which one is correct , and I’ll happily argue that the other is in fact correct! (I think you’re going to say Square extending Rectangle is correct lest Rectangle break Square’s invariants, but I’m not certain. What language you’re operating in may influence the matter; for…
Re: Inheritance Often Doesn't Make Sense
#63Oh, come on. The title submitted to HN is "Inheritance often doesn't make sense"; the actual title of the article is "Why inheritance never made any sense". Are you kidding me? Do we really need, in 2018, another article continuing this particular religious war? Inheritance is just another tool in the software engineer's toolkit. When you need that tool, use it; when you don't, don't. But taking a position where you…
I hear the author. Just the same, at 50k ft, it just seems like the same subject on a different topic. That subject is: Peogramming / software engineering is imperfect. And sometimes things break and need to be refactored.
Why should this profession be any different than any other. The quest for The Holy Grail of Perfection is nobel, but we'll never find it.
I'm not suggesting sloppiness and lower standards, but a sense of theory is great but the reality is reality will never be that perfect.
Use the right tool available at the time. When that tool is no longer right and/or effective then replace it. Keep moving.
Re: Inheritance Often Doesn't Make Sense
#64> you cannot use a square everywhere you can use a rectangle (for example, you can’t give it a different width and height) Can someone come up with a better example here? Intuitively, I would say, "Yes, if you ask me for any rectangle, and you reject a square, you are wrong." If you say you can use any rectangle to do your thing, you should absolutely be able to also use a square. Why am I not convinced with the give…
> and you can't just will it to have a different width and height and expect it to obey you through some force of nature I think you have let functional programming and immutable data-structures bias your world view. The real world is mutable and the wonder of the digital mutable world is that it is pretty much just will-alone that can set attributes as you describe. It is immutability that is a trendy but artificial…
As usual the truth is somewhere in the middle, which is why I don’t like the periodically recurring discussions why OO is bad, FP is good or vice versa. I think the article splits up the issue quite nicely, the conclusion I get from it is that the answer to the question whether to use inheritance or not is ‘it depends’.
Re: Inheritance Often Doesn't Make Sense
#65A couple of other comments have argued that "ontological inheritance" and "abstract data type inheritance" are actually the same thing: > This is because Squares are Liskov substitutable for Rectangles... which is because Squares are, platonically, a kind of Rectangle. > If the type system is sound and expressive enough, ontological inheritance ( this thing is a specific variety of that thing) and abstract data type…
I always find that the common example of Rectangles and Squares leads me to a different conclusion. It assume that the best way to go about is to only have a single sideLength method, but from a data structure perspective it seems more obvious that the Squares class substitute instead the validation method by adding constraints that a valid square only exist when both sides are equal. Rectangle class must already hav…
Re: Inheritance Often Doesn't Make Sense
#66Earlier quoted context omitted.
No. Mutation essentially breaks subtyping. The infamous ArrayStoreException in Java is the story of how references (which should be invariant) are treated as covariant and therefore causes runtime exceptions.
Which is only because Java doesn't understand contravariance. In Scala, that problem no longer exists.
Re: Inheritance Often Doesn't Make Sense
#67Earlier quoted context omitted.
> A common example that is used is when you have a Rectangle.setSize(int width, int height) method. Isn't the fact that we defined a method that changes both sizes at the same time the problem in this case? I mean, if we had two independent methods like `setBase(int)` and `setHeight(int)` this wouldn't be a problem at all (with the assumption, of course, that you accept the fact that the base changes when you change…
The same issue exists for Java Lists. Java lets you pass in subtypes of the type you specified in the List ie it treats them covariantly. This would be correct if the List was immutable but, as you can write to the List, you can blow the type relationship at runtime. In theory a List which you can both read and write should be invariant in the type parameter but this is useless in practice. So Java gives you a useful…
Also, I posed a question asking if I'm wrong in thinking something, was a downvote really warranted? (Not you specifically, but whoever downvoted)
Re: Inheritance Often Doesn't Make Sense
#68Earlier quoted context omitted.
> If you have code that is set up to handle Rectangles, and you give that code a Square, then the code will handle the Square correctly. Hmm...try setting different widths and heights on your square.
Try calculating the diagonal length of your rectangle, where that length is, by definition, 1.414 * width. Alternatively, notice that if your definition of a "rectangle" includes the ability to arbitrarily modify its own width and/or height, then squares are not Liskov substitutable for rectangles and also aren't a kind of rectangle in the "meaning" sense given by definition 1 above. Going by the Liskov criterion, a…
Re: Inheritance Often Doesn't Make Sense
#69Earlier quoted context omitted.
Which is only because Java doesn't understand contravariance. In Scala, that problem no longer exists.
No. When references or arrays of references are treated as contravariant, you would have the opposite problem of ArrayReadException. You can now store things into arrays safely but you can no longer extract things from arrays safely.
EDIT: Good reference: https://www.atlassian.com/blog/software-teams/covariance-and...
Re: Inheritance Often Doesn't Make Sense
#70Earlier quoted context omitted.
This is interesting. I find that inheritance as a code reuse tool pushes developers in the direction of taking whatever class they have and tuck some new properties to a subclass. On the other hand, if you realise that a square is a rectangle with the same width and height, why should you bother at all with creating a new class? A new constructor (or an helper function) should be all you need
> On the other hand, if you realise that a square is a rectangle with the same width and height, why should you bother at all with creating a new class? A new constructor (or an helper function) should be all you need What if you have a function that only knows how to operate on squares? Forcing it to accept Rectangles will be unnatural. Of course we can use just a single type Rectangle with two constructors, but inh…
It's better than nothing as you can guarantee that an instance of Square is a square, but you still need to handle squares disguised as Rectangle.
You could throw in dependent types and force rectangles to have different width and height, but that doesn't really help in getting nicer API.
If I had to do something like this in a real program I would take these issues as a sign that I need to step back and re-evaluate my design. I'd look at what I want to use these types for and try to come up with the best approach for that specific case.