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.