2009-04-08 7 views
5

Ho una classe base che ha un metodo getType() astratto. Voglio che le sottoclassi siano in grado di implementare questo metodo e fornire la classe reale da utilizzare.Restituisce un tipo di classe nidificata in Java

Nel codice, qualcosa di simile al seguente:

public abstract class A { 
    public static interface Tile; 

    protected abstract Class<Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected abstract Class<A.Tile> getTileClass() { 
     MyTile t = new MyTile(); // WORKS 
     return MyTile;   // ERROR HERE 
    } 
} 

Il problema qui è che ottengo "MyTile non può essere risolto" nella linea marcata. Così sto cercando di restituire questo invece:.

ritorno nuova MyTile() getClass()

ma ora Eclipse mi dice:

Tipo non corrispondente: non può convertire da Classe < acquisizione n. 1 di? si estende B.MyTile > alla Classe < A.Tile >

che io non sono nemmeno sicuro se c'è forse un bug in Eclipse qui in alto (cattura # 1?).

Successivamente, mi sto arrendendo alle interfacce e cerco di utilizzare una classe Tile di base astratta. Con un po 'di aiuto da Eclipse, io alla fine con il seguente codice che sembra per compilare:

public abstract class A { 
    public static abstract class Tile; 

    protected abstract Class<? extends Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile exends A.Tile { } 

    @Override 
    protected abstract Class<? extends A.Tile> getTileClass() { 
     return new MyTile().getClass(); // WORKS 
     return MyTile;     // "Cannot be resolved" 
    } 
} 

Così ho praticamente sembra di avere tre domande:

1) E' possibile arrivare a questo lavoro con A . Essere un'interfaccia?

2) Quando si utilizza una classe base, Class<? extends X> è davvero la strada giusta da percorrere?

3) E come posso restituire il mio riferimento di classe B.MyTile nidificato all'interno del metodo? Il fatto di dover fare new MyTile().getClass() non può essere corretto, vero?

+0

Probabilmente restituire un 'Class' invece di un oggetto non riflettente è una cattiva idea. –

+0

@Tom Restituzione di una classe nel contesto di tipi controllati è uno schema molto comune, che consente di controllare il tipo * checked * di, ad esempio, una raccolta, in fase di esecuzione. Non conosco altro modo, infatti ... – Varkhan

risposta

6

L'override di tipo generico e covariante non funziona molto bene insieme. Devi dichiarare esplicitamente getTileClass() come restituire una classe che può essere una sottoclasse di A.Tile.

È inoltre possibile accedere all'oggetto classe di MyTile senza installarlo, con MyTile.class.

Prova a modificare:

public abstract class A { 
    public static interface Tile; 

    protected abstract Class<? extends Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected Class<MyTile> getTileClass() { 
     return MyTile.class; 
    } 
} 

Ancora meglio sarebbe quella di fare un generico. Hai ancora a usare estende nella definizione del tipo di classe, ma si può essere un po 'più specifico:

public abstract class A<T extends A.Tile> { 
    public static interface Tile; 

    protected abstract Class<? extends T> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected Class<MyTile> getTileClass() { 
     return MyTile.class; 
    } 
} 
+0

probabilmente copia e incolla l'errore, ma un metodo astratto può avere un corpo? corretto dovrebbe essere "protetto Classe getTileClass {..." –

+0

@Carlos si, quello era un overazger c/p – Varkhan

+0

Buona risposta. È un problema solo a causa della covarianza o in generale? – Uri

-1
public abstract class A { 
    public static interface Tile {}; 

    // I return something that is-a Tile 
    protected abstract Tile getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected abstract Tile getTileClass() { 
     return new MyTile(); 
    } 
} 

Non c'è bisogno di farmaci generici, si vuole solo dire che si restituisce un Affianca o Tile sottoclasse.

Per inciso, un'interfaccia statica pubblica in una classe è un "odore di codice"; o rendilo protetto, quindi solo le sottoclassi di A possono implementare Tile, o metterle nella sua interfaccia di primo livello. Mettendo in un ma permettendo a chiunque di implementarlo invia un messaggio misto.