Answer boils down to Java does not support lower bounds on parameterized methods, because such a feature is "not useful enough"
, refer to a similar question
Given the following snippet:
package demo;
public class Demo {
interface Foo { void foo(); }
interface Bar { void bar(); }
interface FooBar {
<R extends Foo & Bar> R foobar();
static FooBar create() { return new TypicalJavaFooBar(); }
}
private static final class TypicalJavaFooBar implements Foo, Bar, FooBar {
public void bar() { System.out.println("foo"); }
public void foo() { System.out.println("bar"); }
public <R extends Foo & Bar> R foobar() {
return (R) this;
}
}
public static void main(String[] args) {
FooBar x = FooBar.create();
Foo foo = x.foobar();
Bar bar = x.foobar();
x.foobar().foo();
x.foobar().bar();
}
}
Without the explicit cast to R
in TypicalJavaFooBar#foobar
compiler fails with the following error
Error:(13, 20) java: incompatible types: demo.Demo.TypicalJavaFooBar cannot be converted to R
My question is why? To me, it seems that the compiler should have enough info since TypicalJavaFooBar
is clearly defined to implement both Foo
and Bar
; why isn't that enough to satisfy the Foo & Bar
constraint?
UPDATE
The main goal of this exercise is to define the following contract: calling method foobar
on an instance of a FooBar
is guaranteed to return something that implements both Foo
and Bar
.
The type parameter R
is bound to the method by the calling code and could theoretically be Baz implements Foo, Bar
; see, for example, Collections.emptySet()
, whose type parameter is determined by the caller and can be influenced by a type witness.
To do what you are apparently attempting, you would need to move the type parameter onto the interface FooBar
and have TypicalJavaFooBar implements Foo, Bar, FooBar<TypicalJavaFooBar>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With