#TodayILearned: Multiple inheritance in the #java #programming 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
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 #java'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
That was impossible for my base interface. - 2/2
Why, you way ask? Because as it is in use as a base interface, my classes extend / implement it in various ways. Incompatible ways.
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.
And as long as IEmptive is referred to as Consumer<? super IEmptive>, the world is fine, and #Java 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.
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 #inheritance for me.
Thanks, #Java #programming language, that's exactly the level of #objectOriented architecture I always desired.
@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).
Cybrespace is an instance of Mastodon, a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.