risposta si riduce a Java does not support lower bounds on parameterized methods, because such a feature is "not useful enough"
, fare riferimento a un similar questionPerché il compilatore Java non può inferire correttamente l'ereditarietà?
Dato il seguente frammento:
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();
}
}
Senza il cast esplicito a R
in TypicalJavaFooBar#foobar
compilatore non riesce con il seguente errore
Error:(13, 20) java: incompatible types: demo.Demo.TypicalJavaFooBar cannot be converted to R
mio la domanda è perché? Per me, sembra che il compilatore debba avere abbastanza informazioni dal TypicalJavaFooBar
è chiaramente definito per implementare sia Foo
e Bar
; perché non è sufficiente per soddisfare il vincolo Foo & Bar
?
UPDATE
L'obiettivo principale di questo esercizio è quello di definire il seguente contratto: metodo foobar
invitando un'istanza di un FooBar
è garantito per tornare qualcosa che implementa sia Foo
e Bar
.
@horatius Questo non ha nulla a che fare con questa domanda. – chrylis
In 'TypicalJavaFooBar' è possibile modificare il tipo di ritorno del metodo' foobar' in "TypicalJavaFooBar', che elimina anche il cast. Mentre questo non risponde alla tua domanda, questo è quello che probabilmente farei in questa situazione.Anche se generalmente preferisco la composizione al di sopra dell'eredità e quindi sono improbabile incontrare questa situazione. :-) – Waldheinz
@Andrey, sfortunatamente il tuo "obiettivo principale" non è effettivamente possibile nel sistema di tipi di Java. È possibile restituire qualcosa che è garantito per implementare un'interfaccia specifica, ma non è possibile esprimere "qualcosa che implementa entrambe le interfacce". –