I have some code with this general structure:
interface Func<A> {
double apply(Optional<A> a);
}
class Foo {
public double compute(Func<Double> f) {
// Sometimes amend the function to do something slightly different
Func<Double> g = f;
if (someCondition())
g = oa -> Math.max(0, f.apply(oa));
return g.apply(Optional.of(3.14)) + g.apply(Optional.empty());
}
}
This, in itself, works well enough. Now I want to be more liberal such that if someone has, say, a Func<Number> or Func<Object> instead of a Func<Double> they can still pass that into compute. A priori this ought to be safe enough. Very well, so I change it to
public double compute(Func<? super Double> f) {
Func<? super Double> g = f;
if (someCondition())
g = oa -> Math.max(0, f.apply(oa));
...
Unfortunately now the lambda doesn't typecheck (says Eclipse) because the type of oa cannot be passed to f.apply.
The assignment of f itself to g doesn't seem to worry the compiler, and the problem does not arise if the argument to apply is A rather than Optional<A>.
Unfortunately there doesn't seem to be a way to name the ? super Double argument type so I can use it again as the type for g and/or replace the lambda with an old-fashioned inner class.
For example, this is not even syntactically allowed:
public <T super Double> double compute(Func<T> f) {
Func<T> g = f;
...
Is there any reasonably elegant way to make this work?
The best I've come up with so far is
public double compute(Func<? super Double> f) {
if (someCondition())
return computeInner(oa -> Math.max(0, f.apply(oa)));
else
return computeInner(f);
}
private double computeInner(Func<? super Double> g) {
return g.apply(Optional.of(3.14)) + g.apply(Optional.empty());
}
The compiler accepts this, but the indirect call for no other reason than to make the type checker happy is not really what I'd call elegant.