Se ho un'interfaccia e un'implementazione:
interface BaseInterface{ }
class Base implements BaseInterface{ }
E da qualche altra parte ho un metodo:
<T extends Base> T foo() { /* return object of class T */ }
foo()
deve essere chiamato esplicitamente con Base per poterlo assegnare all'interfaccia. Questo funziona bene:
BaseInterface a = <Base>foo();
Bene ... ma come faccio a chiamare esplicitamente il seguente metodo?
<V extends Base> Map<String, V> bar() { /* return object of Map<String, V> */ }
Nessuno di questi sembra funzionare:
Map<String, ? extends BaseInterface> m = <Base>bar();
Map<String, ? extends BaseInterface> m = <String, Base>bar();
Map<String, ? extends BaseInterface> m = <Map<String, Base>>bar();
risposte:
2 per risposta № 1Penso che tu stia leggermente fraintendendo come usare i generici.
Quello che hai ora è questo:
<T extends Base> T foo() {...}
che, in inglese, significa questo foo
restituirà un oggetto che è una sottoclasse di Base
(ricorda che sottoclasse significa "questa classe o qualsiasi classe figlia"). Ma foo
non accetta alcun argomento quindi è impossibile per l'implementazione di foo
per sapere cosa T
è legato a, né lo fa importa che cosa T
è legato a: tutto foo
a cui importa, e a tutti i chiamanti interessa, è che restituisce una sorta di Base
.
In sostanza, quello che hai è equivalente a questo:
Base foo() {...}
Non è necessario utilizzare i generici in questo caso perché foo
non ha bisogno di preoccuparsi delle informazioni sul tipo: restituisce solo una sottoclasse di Base
. Sarebbe diverso se lo facessi:
<T extends Base> T doSomething(T input)
perché doSomething
ha bisogno delle informazioni di tipo generico per decidere quale sarà il tipo di ritorno.
Piuttosto che dichiarare foo
e bar
come generici, perché non solo dichiararli come
Base foo();
Map<String, Base> bar();
o, ancora meglio,
BaseInterface foo();
Map<String, BaseInterface> bar();
Ora puoi scrivere il tuo codice cliente:
BaseInterface a = foo();
Map<String, BaseInterface> m = bar();
So che questo non risponde direttamente alla tua domandama penso che nel tuo caso (dato il codice di esempio) non hai davvero bisogno di usare i generici per risolvere il tuo problema. È facile confondere i generici con il polimorfismo. In questo caso il polimorfismo è tuo amico.
0 per risposta № 2
Map<String, Base> m = bar<Base>();
In base al codice che hai pubblicato, il parametro generico V della barra del metodo dovrebbe essere Base o una classe derivata Base. BaseInterface non deriva da Base. È Base che implementa BaseInterface.