4 comments

[ 3.3 ms ] story [ 23.6 ms ] thread
Why ask this question about Java in particular? I think the real question is whether inheritance is useful in nominal type systems with objects and interfaces.

And I think the real answer is yes. Inheritance is very nice in the API for GUIs. I've never seen the idea applied usefully elsewhere, though I'm sure there are examples.

The real answer is no. Inheritance is absolutely unnecessary for API for GUIs. Absolutely unnecessary. If we are talking about GUI callbacks, what you want is a type systems that's statically-typed, with functions as first-class citizens (Hindley-Milner type system preferred) and with records (which are syntactic sugar anyway, they are just glorified tuples). Put a bunch of functions into a record and there's your GUI callback. This is a much cleaner and simpler way of doing it.

Inheritance is a fundamentally flawed concept in type systems. It suffers from the fragile base class problem. Josh Bloch, writer of Effective Java, recommends using composition over inheritance. If you want inheritance so that you can selectively override event handlers, and fall back on default implementations... you want something that's broken, because that suffers from the fragile base class problem. You need a guarantee that the superclass you are overriding won't call your subclass methods in an unexpected way... in other words, you need implementation details. A better way is to explicitly call default handlers on the superclass.

I wasn't thinking of callbacks, but rather of the generic plumbing for, e.g., GUI elements that contain other GUI elements. And I never suggested it was necessary, only useful: it's nice to have Button be a type, but it's also nice to have addToWindow take any Element. There are GUI systems that don't do this---the DOM, for example---but they have their own warts.

I don't follow the last two sentences.

Just read the original post and think GUI callbacks, and you'll get what I was trying to convey.

You can have addToWindow take any element, there just has to be a function called 'asElement' which will take your type and produce a relevent 'element' data structure. Further, you can use Haskell-style type classes or ML-style functors to make this easy and polymorphic.