Live data from Hacker News

Inheritance Often Doesn't Make Sense

sicpers.info

31–40 of 255 posts

Re: Inheritance Often Doesn't Make Sense

#31

I don't understand why some functional programmers have so much difficulty with the concept of inheritance. Discriminated Unions and pattern matching is just inheritance and virtual dispatch turned inside out. Yet no one is naval gazing about whether their algebraic datatypes are 'ontological' or not. I also really wish people wouldn't try and dismiss concepts they're ignorant of: because multiple inheritance is inco…

Yes it's true that discriminated unions and pattern matching is just inheritance and virtual dispatch turned inside out. But discriminated unions and pattern matching are easier to use, easier to understand than inheritance and virtual dispatch.

And you don't need to struggle with principles like "is-a relationship" which can be confusing.

Re: Inheritance Often Doesn't Make Sense

#32
post #9

A 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…

The thing is, rectangles are a kind of square, and squares are a kind of rectangle, from different perspectives.

Re: Inheritance Often Doesn't Make Sense

#33
post #12

This 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…

> 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 height).

Am I creating a different class of problems this way?

Also, this seem rather specific to rectangles and squares. Do real-world objects (think `List` in Java) have this kind of problems at all?

Re: Inheritance Often Doesn't Make Sense

#35
post #20

> 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…

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.

Re: Inheritance Often Doesn't Make Sense

#36
post #31

I don't understand why some functional programmers have so much difficulty with the concept of inheritance. Discriminated Unions and pattern matching is just inheritance and virtual dispatch turned inside out. Yet no one is naval gazing about whether their algebraic datatypes are 'ontological' or not. I also really wish people wouldn't try and dismiss concepts they're ignorant of: because multiple inheritance is inco…

Yes it's true that discriminated unions and pattern matching is just inheritance and virtual dispatch turned inside out. But discriminated unions and pattern matching are easier to use, easier to understand than inheritance and virtual dispatch. And you don't need to struggle with principles like "is-a relationship" which can be confusing.

But discriminated unions and pattern matching are easier to use, easier to understand than inheritance and virtual dispatch.

That seems incredibly subjective. It's 50/50 for me, I just go with the grain with the language I'm using. I'll admit that in practice pattern matching wins due to the depressing lack of multiple dispatch in OO and pseudo-OO languages.

And you don't need to struggle with principles like "is-a relationship" which can be confusing.

Why would you struggle with that question with inheritance and not DUs? what is it about DUs that make it not an issue?

Re: Inheritance Often Doesn't Make Sense

#37
post #15

> 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…

The deeper problem is that many domains cannot be modelled as hierarchical taxonomies, but only as ambiguous categories. This is a theory expounded by, amongst others, George Lakoff in his book "Women, Fire and Dangerous Things"[1] and elsewhere. Such cognitive categories are fuzzily defined, often overlap, and represent a collection of traits and properties that members of a category share some or all of. But different members can belong to the category to a greater or less extent, or be better or worse examples of it. E.g. both ostriches and sparrows are birds, but sparrows are usually considered a better example of the category birds.

Like the process of developing scientific taxonomies, efforts to model these kind of domains using OO techniques frequently run into edge cases that defy concrete classification. E.g. can all birds fly? Clearly, flight is an extremely important trait of the class "bird", but we also recognise flightless birds as birds, which means objects can lack an important trait of a category, but still belong to it, albeit as a worse example.

This is not just a theoretical problem. Imagine trying to invent a set of classes to model computing devices for an IT asset management system. What exactly constitutes a smartphone, vs. a tablet, vs. a laptop, etc.? It's easy to imagine the attributes and behaviors you might attach to these classes, but properly mapping every real world device onto them is extremely difficult. You are always going to get edge-case devices that straddle multiple classifications, or exclude some behavior that is assumed to be critical to devices of its type.

The result is that systems trying to model such domains end up with a variety of problems: Some impose a rigid, but essentially arbitrary, taxonomy, with the result that users struggle to use it properly. Edge-cases require special, out-of-band handling, e.g. users understanding that the system cannot properly represent items of a particular type, and that you have to accept a misclassification, or misuse the system slightly in order to make it work.

Some systems flatten and generalise the taxonomy into a single superclass, perhaps called "Device" in our example, that holds all the attributes and behaviors of all the former subclasses. This requires users to then interrogate objects of this generic type and essentially determine their "actual" type on an ad-hoc basis, with the result that they may be treated differently, or incorrectly, by different processes, depending on the heuristics that were applied in that case.

And finally many systems just abandon the idea of internally representing the taxonomy in concrete terms at all. As edge-cases proliferate, and that idea that "every X is just a specialised case of Y", is taken to its conclusion, the concrete taxonomy dissolves and is replaced with a general taxonomical abstraction. A new, more flexible object system is implemented on top of the native object system, such that users of the system can define their own classes, at runtime. These systems will support tagging and multiple membership, and other devices for representing complex taxonomies. This solves the problem of representation, but only by abrogating responsibility for defining it entirely to users of the system. These users are then faced with the task of developing the taxonomy from scratch in userland. In an organisation where different departments need to agree on a common taxonomy, this process is often centralised, and a single simplified set of classes is presented to sub-users. But then edge-cases to this taxonomy start to emerge, and the process repeats itself. This is how layers of abstraction proliferate.

[1] https://en.wikipedia.org/wiki/Women,_Fire,_and_Dangerous_Thi...

Re: Inheritance Often Doesn't Make Sense

#38
Unless your program's goal is to ontologically categorize objects, #1 is a trap that will just bite you in the ass.

In the physical world, if I have a rectangle shaped box I want to cover, I don't want a square, no matter how much "squares are rectangles". It's no different in a program. What really matters is the behavior and goals of your program. It's cute to say squares are rectangles but if your program needs to let your user independently set width and height then a square is completely useless.

Re: Inheritance Often Doesn't Make Sense

#39
post #20

> 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…

To fix it in real world you make factory abstraction which you feed with initial data and then factory knows if it is rectangle to be produced or a square. So developer should not be concerned with cats or dogs, developer should be able to call Feed() method.

But we all know how this ended in Java.

Re: Inheritance Often Doesn't Make Sense

#40
post #3

Oh, 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…

> But taking a position where you say it's never the right tool or, conversely, always the right tool makes you sound ignorant and inexperienced. Neither of those positions is advocated by the article, so who exactly are you talking about? In fact, you seem to have assumed that "make sense" in the title referred to the issue of whether or not to use inheritance, whereas in fact the article is concerned with the custo…

He never read the article.
Post reply on HN