/ / Richiamo esplicito del metodo generico: java, generics

Chiamare esplicitamente un metodo generico: java, generics

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 № 1

Penso 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.