Reputation: 115
What I'd like to do is something like this:
Function<Function<Bill, Optional<?>>,Function<Bill, Optional<String>>> has =
fn -> b -> fn.apply(b).isPresent()
? emptyStrOpt.get()
: Optional.of("Missing");
A Bill
may have a Claim
. I'd like to do this:
has.apply(toClaim)
static final Function<Bill,Optional<Claim>> toClaim = b -> Optional.ofNullable(b.getClaim());
The compiler doesn't like this:
Required type: Function <Bill,Optional<?>>
Provider: Function <Bill,Optional<Claim>>
I figure to get around this, I'd write something like this to cast the function I pass to Object:
static <R> Function<Bill,Optional<Object>> generifyOutput(Function<Bill,Optional<R>> toX){
return b -> toX.apply(b).map(x -> Optional.of((Object) x));
}
static final Function<Function<Bill,Optional<Object>>,
Function<String,
Function<Bill,Function<Bill,Optional<String>>>>> isPresent =
toX -> missingMsg -> b ->
toX.apply(b).isPresent()
? (Bill x) -> emptyStrOpt.get()
: (Bill x) -> Optional.of(missingMsg);
Then call isPresent.apply(generifyOutput(toClaim)).apply("No claim")
But the compiler freaks out, saying that I'm providing Function<Bill, ? extends Object>
instead of Function<Bill,Optional<String>>
Is there something else I can do here? I could just brute-force it like
Function<Bill,Optional<String>> hasClaim =
b -> toClaim.apply(b).isPresent()
? emptyStrOpt.get()
: Optional.of("No claim");
This seems a little ham-handed though, repeating the same logic for each nullable member of Bill
Upvotes: 0
Views: 63
Reputation: 102902
Just make that ? extends Optional<?>
instead; Optional<Claim>
is compatible with that.
Generics typing is invariant, meaning, only the exact thing matches, sub/supertype relationships do not apply. Because that's just how generics are defined. It is the right variance when both 'reads' and 'writes' can happen. Even in contexts where e.g. writes can't happen, the compiler doesn't know that, therefore, enforces invariance.
? extends
is java-ese for: I want covariance. Hence why this works.
Upvotes: 1