Reputation: 37045
I have a (poor man's) either-type in Java:
public final class Either<L, R> {
final boolean isLeft;
final L l;
final R r;
private Either(final boolean isLeft, final L l, final R r) {
this.isLeft = isLeft;
this.l = l;
this.r = r;
}
// map, right-projection, left-projection, etc.
public static <L, R> Either<L, R> left(final L l) {
return new Either(true, l, null);
}
public static <L, R> Either<L, R> right(final R r) {
return new Either(false, null, r);
}
}
I would like to add a method to join the L or R to an instance of some type T
:
public <T extends L & R> T join() {
return isLeft ? (T)l : (T)r;
}
But Java does not like this generic constraint: T extends L & R
. How can I represent this operation in the Java type system?
Upvotes: 2
Views: 423
Reputation: 140326
You can only do this on an Either
where the two types are related to the type you want to return. Since this isn't generally the case, you need to do this in a static method (or, at least, some method not on the instance of Either
):
static <T> T join(Either<? extends T, ? extends T> either) {
return either.isLeft ? either.l : either.r;
}
Upvotes: 6
Reputation: 34900
You possibly want to describe case when T
extends L
or R
(as it obviouslty doesn extend both of them at the same time). But you can't do such specification in Java.
Do not overcomplicate this case and do just:
public <T> T join() {
return isLeft ? (T)l : (T)r;
}
Upvotes: 0
Reputation: 140457
The constraint that you are putting on your T
here can't work. How is the compiler supposed to know that the L l or R r that you put into your Either object are both L and R at the same time?!
In other words: you want to your result of join()
to be Fruit; than that would require that the "incoming" L l and R r where both Fruits when you created that object. But what happened when you didn't put an Apple and a Banana into your Either, but an Apple and a Scissor? How do you think you could join them under a common supertype?!
Upvotes: 0