Inheritance Often Doesn't Make Sense
11–20 of 255 posts
Re: Inheritance Often Doesn't Make Sense
#12This gets off to a bad start: > There are three different types of inheritance going on. > 1. Ontological inheritance is about specialisation: this thing is a specific variety of that thing (a [soccer ball] is a sphere and it has this radius) > 2. Abstract data type inheritance is about substitution: this thing behaves in all the ways that thing does and has this behaviour (this is the Liskov substitution principle)…
This method is of course of type void. The problem is that by calling setSize, there is an implicit return type: the type of the object. This is assumed to be Square because this is the type of the object, but in reality the setSize method takes a Rectangle and produces a Rectangle.
If you would have a method stretch: Rectangle -> Rectangle, the Liskov substitution principle wouldn't be violated: you could substitute a Square for a Rectangle and everything would work the way it's supposed to.
Re: Inheritance Often Doesn't Make Sense
#13Oh, 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…
Re: Inheritance Often Doesn't Make Sense
#14This gets off to a bad start: > There are three different types of inheritance going on. > 1. Ontological inheritance is about specialisation: this thing is a specific variety of that thing (a [soccer ball] is a sphere and it has this radius) > 2. Abstract data type inheritance is about substitution: this thing behaves in all the ways that thing does and has this behaviour (this is the Liskov substitution principle)…
> 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.
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 sentient rectangle can double its own width and still be a rectangle, but a sentient square cannot double its own width and still be a square.
Re: Inheritance Often Doesn't Make Sense
#15Alternatively, 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 width;
// No need to have "height" field because Square guarantees that height ==
// width.
public:
virtual size_t getWidth() const { return width; }
virtual size_t getHeight() const { return width; }
};
class Rectangle : public Square {
size_t height;
// A rectangle allows height to be different from width.
public:
virtual size_t getHeight() const override { return height; }
};
See? This makes OO hard because it's hard to decide which should be the subtype of which intuitively, and people get even more confused since the arrow is contravariant in its left argument and the relationship would sometimes appear reversed. There in fact is one correct answer but people often get it wrong. You need some serious appreciation of OO to know which.Here are some more examples that can cause confusion. Suppose we have Reference (which can be read or written), ReadableReference (read-only) and WritableReference (write-only). From a purity perspective, should we have Reference inherit from both ReadableReference and WritableReference (ignoring OO languages that don't allow multiple inheritance), or should we have ReadableReference and WritableReference inherit from a single base class Reference? This kind of question frequently trips people up.
Re: Inheritance Often Doesn't Make Sense
#16This article seems to be confused about what abstract data type inheritance is, as exemplified by "As a type, this relationship is reversed: you can use a rectangle everywhere you can use a square (by having a rectangle with the same width and height), but you cannot use a square everywhere you can use a rectangle (for example, you can’t give it a different width and height)." If an abstract data type X inherits from…
Yes you can. You just need to make a clean separation between mutable variables and immutable variables. Then mutable variables must be invariant, and immutable variables can enjoy subtyping.
Alternatively, classify mutable variables further and make references carry information about whether only reading/writing is allowed through this reference. Then read-references enjoy the usual covariant subtyping, and write-references enjoy contravariant subtyping.
Re: Inheritance Often Doesn't Make Sense
#17> 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…
Re: Inheritance Often Doesn't Make Sense
#18Oh, 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…
The concept of "types" in programming languages is another great example -- there are syntactic type declarations, memory-level types to specify which bytes mean what, things like typeclasses or interfaces which give you runtime polymorphism, the "type" you have in your head when you're thinking about what kind of data your code needs to handle... before you even start to have a discussion, you need some idea of what you're talking about.
Re: Inheritance Often Doesn't Make Sense
#19This gets off to a bad start: > There are three different types of inheritance going on. > 1. Ontological inheritance is about specialisation: this thing is a specific variety of that thing (a [soccer ball] is a sphere and it has this radius) > 2. Abstract data type inheritance is about substitution: this thing behaves in all the ways that thing does and has this behaviour (this is the Liskov substitution principle)…
A common example that is used is when you have a Rectangle.setSize(int width, int height) method. When you make Square a subclass of Rectange, the Liskov substitution principle is violated. I think this (well-known) example is what the author of the article wants to refer to. This method is of course of type void. The problem is that by calling setSize, there is an implicit return type: the type of the object. This i…
Re: Inheritance Often Doesn't Make Sense
#20Can 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 given example? Because fundamentally, I don't think "set the width and height" counts as something you can do with a rectangle. A rectangle has a width and height, 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. What you can do is construct a new rectangle and destroy the old one in the process.
In other words, if you expect to change the shape of the item, you should not permanently identify the item by its shape. The given example is a bit like saying "The superclass Animal has a method becomeCat which turns any animal into a cat." and then feigning surprise when your code breaks for any non-feline animal.