: Multiple inheritance in the language is problematic.

In my case, subclasses wind up with the same super interface via multiple inheritance paths. And as long as the super interface isn't generic, this gets resolved just fine.

As soon as we start generifying that super interface, Java will complain that the newly added varying type parameters don't match.

Well, no - 1/2

If they matched, my architecture wouldn't have needed multiple classes, now, would it? - 2/2

Show thread

This got triggered a few days ago by me desiring to add consumer and function abilities to my base interface: doIfPresent(then, otherwise) and doIfEmpty(then), modelled after how 's own Optional class does ifPresent(Consumer).

But the Optional class is generified. And my base interface thus far hadn't been. And that makes a difference: the auto-injected argument to the Optional.ifPresent consumer is typed to whatever instantiated the Optional - 1/2

Show thread

Why, you way ask? Because as it is in use as a base interface, my classes extend / implement it in various ways. Incompatible ways.

For instance:
IEmptive > IMessage > Message > XML.
IEmptive > IMessage > IName > Name.
IEmptive > IPair > ILocateFiles, IMessage > ReadFrom.
IEmptive > IPair, IName > Pair, Name > NamePair > UserToken.

So… ReadFrom is IEmptive, and so is UserToken. Both are IPair. And both hold IMessage values, though UserToken implements that as Name.

Show thread

And as long as IEmptive is referred to as Consumer<? super IEmptive>, the world is fine, and is fine.

But that has a drawback: the auto-generated parameter value for the consumer is an IEmptive, rather than, say, a ReadFrom or a UserToken. That forces a type cast. This isn't necessary with Optional.ifPresent(Consumer).

So, can I get rid of that typecast?

The first thing I tried, of course, is to add a type parameter to the IEmptive interface declaration, much like Optional.

Show thread

That required changing the declarations of the subclasses.

First: IMessage. Success!

Then IPair. No problems yet.

Then ILocateFiles. Uh-oh. Cracks are appearing. Alright: manageable.

Then NamePair. Kablammo! No more for me.

Thanks, language, that's exactly the level of architecture I always desired.


Show thread

The problem with this is not, that there are no solutions to work around this limitation in the language. Solutions exist.

It's just that implementing those would require yet another load of copy-pasted, , which is exactly what I was aiming to avoid by using a base interface in the first place.

You're making it difficult to design clean architectures, Java.

Very difficult.

@aeveltstra hmm. is it substantially better in other OOP languages?
if not..... maybe OOP is the problem....

@grainloom OOP definitely is part of the problem. This simply doesn't happen in non-OO programming languages.

And part of the problem are the choices made by the java language specification authors, and have been upkept over the years (i.e. Mark Reinhold, chief language and platform architect).

It won't happen in OOP languages that lack generics (JS, PHP5). And it won't happen in languages that allow multiple inheritance (c++), or use non-generic trait injection (rust).

Sign in to participate in the conversation

Server run by the main developers of the project 🐘 It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!