2009-04-08 6 views
5

J'ai une classe de base qui a une méthode getType() abstraite. Je veux que les sous-classes puissent implémenter cette méthode et fournir la classe réelle à utiliser.Renvoie un type de classe imbriqué dans Java

Dans le code, quelque chose comme ce qui suit:

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 
    } 
} 

Le problème ici est que je reçois « MyTile ne peut être résolu » dans la ligne marquée. Donc, je suis en train de retourner ce lieu.

return new MyTile() getClass()

mais maintenant Eclipse me dit:

Incompatibilité de type: ne peut pas convertir Classe < capture # 1-of? étend B.MyTile > à la classe < A.Tile >

que je ne suis même pas sûr s'il y a peut-être un bug dans Eclipse ici top (capture # 1?).

Ensuite, j'abandonne les interfaces et j'essaie d'utiliser une classe de carreaux de base abstraite. Avec l'aide d'Eclipse, je me retrouve avec le code suivant qui semble compiler:

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" 
    } 
} 

Je semble essentiellement avoir trois questions:

1) Est-il possible d'obtenir ce travail avec A .Tile étant une interface?

2) Lors de l'utilisation d'une classe de base, Class<? extends X> est-il vraiment la bonne façon de procéder?

3) Comment puis-je retourner ma référence de classe B.MyTile imbriquée à l'intérieur de la méthode? Avoir à faire new MyTile().getClass() ne peut pas avoir raison, peut-il?

+0

Il est probablement mauvais de retourner un 'Class' au lieu d'un objet non-réfléchissant. –

+0

@Tom Retourne une classe dans le contexte des types cochés est un modèle très commun, qui vous permet de vérifier le type * checked * de, par exemple, une collection, à l'exécution. Je ne connais pas d'autre moyen, en fait ... – Varkhan

Répondre

6

Les remplacements de type générique et covariant ne fonctionnent pas très bien ensemble. Vous devez déclarer explicitement getTileClass() comme renvoyant une classe qui peut être une sous-classe de A.Tile.

Vous pouvez également accéder à l'objet de classe de MyTile sans l'instancier, avec MyTile.class.

Essayez ceci:

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; 
    } 
} 

Mieux encore serait de faire un générique. Vous devez toujours utiliser étend dans la définition du type de classe, mais vous pouvez être un peu plus précis:

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

probablement copier et coller erreur, mais une méthode abstraite peut avoir un corps? correct devrait être "protégé Classe getTileClass {..." –

+0

@Carlos oui, c'était un trop grand c/p – Varkhan

+0

Bonne réponse. Est-ce un problème simplement à cause de la covariance ou en général? – 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(); 
    } 
} 

Pas besoin de médicaments génériques, vous voulez juste dire que vous retournez une tuile ou tuile sous-classe. Incidemment, une interface statique publique dans une classe est une "odeur de code"; soit le rendre protégé, donc seules les sous-classes de A peuvent implémenter Tile, ou le placer dans sa propre interface de premier niveau. Mettre dans un mais permettre à quiconque de l'implémenter envoie un message mélangé.

Questions connexes