2015-08-25 12 views
7

Io uso due interfacce:Generico Chaos Java

public interface Receiver<T> { 

    public void receive(T obj); 

    public Set<Class<? extends T>> getInterests(); 

} 

public interface Distributor<T> extends Receiver<T> { 

public void register(Receiver<T> receiver); 

} 

Il mio problema che voglio registrare un distributore in un distributore per esempio Distributor<Object> registro == ==>Distributor<String>

Il mio primo pensiero è stato quello di cambiare il metodo di registro per register(Receiver<? extends T> receiver). Ma se voglio ottenere le classi il ricevitore è intrested nei getInterests metodo potrebbe restituire qualcosa come Set<Class<? extends ? extends T>>. Indiretto Ottengo qualcosa come Set<Class<? extends T>> ma ho sperimentato che i caratteri jolly di transito non sono possibili in Java.

Qualcuno ha un'idea?

EDIT: Per fare un esempio:

public void register(Receiver<? extends T> receiver){ 
    Set<Class<? extends T>> interests = receiver.getInterests(); 
    //Problem because receiver.getInterests is 
    //Set<Class<? extends ? extends T>> 
    ... 
} 
+2

Può fare un esempio di una riga di codice, che non può essere compilato per voi? Sembra che il codice verrà compilato. –

risposta

7

Il tuo problema è che i generici Java sono completamente invarianti, a meno che non li fai variante utilizzando ? extends o ? super jolly.

A Set<Class<? extends T>> può contenere solo espressioni del tipo compile-time Class<? extends T>. Class<String> non è lo stesso tipo di Class<? extends T> (anche se è convertibile per quel tipo).

Si desidera un set che possa contenere qualsiasi tipo convertibile in Class<? extends T>.

che sarebbe un Set<? extends Class<? extends T>>

+1

'Class' è definitiva? Come può esserci qualcosa che estenda la Classe? – Codebender

+2

@Codebender: 'extends' in realtà significa" convertibile in ". 'Classe ' è convertibile in 'Classe '(anche se non a' Classe '; occorrono _both_'? estende 'i caratteri jolly). – SLaks

+1

@Codebender 'Classe ' può avere sottotipi tramite generici anche se la classe è definitiva e non può essere sottoclassata. 'extends' ha un significato più ampio se usato in un bound. – Radiodef

1

Si potrebbe aggiungere un metodo di supporto che utilizza una variabile anziché jolly

public void register(Receiver<? extends T> receiver) 
{ 
    register2(receiver); 
} 

private <S extends T> void register2(Receiver<S> receiver) 
{ 
    Set<Class<? extends S>> interests = receiver.getInterests(); 
    ... 
} 

D'altro canto tipo, metodo

public Set<Class<? extends T>> getInterests(); 

è probabilmente destinato per restituire un covariant Set o set di sola lettura. Idealmente jolly deve essere utilizzato

public Set<? extends Class<? extends T>> getInterests(); 

ma so, ci sono troppi caratteri jolly maledetti ...