2013-03-27 13 views
8

Sto cercando di capire come ottenere i generici per saltare attraverso i cerchi.Generics Puzzler

ho:

interface Root { } 
interface Middle extends Root { } 
class Type implements Root { } 

E molti "sottotipo" classi:

class Subtype1 extends Type implements Middle { } 
class Subtype2 extends Type implements Middle { } 
... 

Quello che voglio è quello di dichiarare una classe con due parametri di tipo T e S, dove T è vincolato da Type e S è vincolato a T e Middle.

Non riesco a vedere un modo con generici per garantire che S si estenda T E implementa Middle. Quello che voglio è qualcosa di simile:

class Handler<T extends Root, S extends T, S extends Middle>; 

o

class Handler<T extends Root, S extends <T extends Middle>>; 

Ma naturalmente non sono legali. Forse c'è della magia che mi manca?

+2

Non puoi farlo. È possibile avere più limiti, ma devono essere 0-1 Class e più interfacce. Non puoi avere un tipo generico in una situazione a più vincoli. Sospetto che questa restrizione sia stata mantenuta perché consentire che il tipo in più limiti creerebbe molta complessità al correttore di sintassi, per quello che è un raro caso limite. – BevynQ

+2

correlati: http://stackoverflow.com/a/13261667/697449 –

+0

Grazie. Anche quello è stato letto, ma ho pensato che fosse possibile che mi mancasse qualcosa nelle specifiche. Casts it is! –

risposta

2

Provare a introdurre una classe astratta che estende SubType e implementa Middle, quindi il suo tipo può essere utilizzato in Handler.

abstract class MiddleSubtype extends Subtype implements Middle { } 

Poi,

class Handler<T extends Root, S extends MiddleSubtype> { //... 

EDIT: seguito dell'aggiornamento alla domanda, la stessa idea sarà simile:

abstract class MiddleType extends Type implements Middle { } 

class Subtype1 extends MiddleType { } 
class Subtype2 extends MiddleType { } 
... 

class Handler<T extends Root, S extends MiddleType> { //... 
+1

Si noti che questo è diverso da 'T estende Root, S estende T ...' sebbene, poiché 'S' non è più legato da' T'. –

+0

Sì e lega il gestore ad un sottotipo. In realtà ho un sacco di sottotipi che significherebbe anche un gruppo di Handler che è esattamente quello che stavo cercando di evitare. –

+0

@NickPalmer Vedere la mia modifica per questa risposta - Penso che questo sia vicino a ciò che rgettman stava suggerendo. –

0

Oppure si potrebbe fare S generico stessa:

interface SInt<A,B> {} 
class Handler<T extends Root, S extends SInt<T, Middle>>{}