2010-09-06 6 views
1

Je suis en train de faire une des opérations suivantes:Coulée des types de classes génériques à des méthodes non génériques ou appelantes de leurs instances?

Dummy d = (Class<Dummy>)super.getEntity(); // incompatible Types - cannot cast 
Dummy d = (Dummy)super.getEntity(); // incompatible Types - cannot cast 
d.foo(); 

ou

Class<Dummy> d = (Class<Dummy>)super.getEntity(); // works 
d.foo(); // method cannot be found 

factice d est défini dans une superclasse abstraite comme suit:

Class<T> dummy; 
public Class<T> getEntity() { return dummy; } 

Est-il possible de appeler une méthode (foo) dans un objet de type classe générique? Le point est que la superclasse ne devrait pas se soucier du type de l'objet, de sorte que la fonctionnalité peut varier selon les classes qui s'étendent.

+1

est votre méthode « getEntity() » sur la superclasse supposée retourner un objet de type ou classe ? Il semble que votre membre devrait être défini comme "T mannequin" au lieu de "Classe dummy" et getEntity() devrait retourner une instance de T. –

Répondre

2

Votre méthode getEntity() retourne un jeton classe , pas une instance de cette classe, de sorte que vous ne pouvez pas appeler foo() sur elle, seules les méthodes définies dans l'interface de java.lang.Class. Vous devez instancier cette classe première (en appelant newInstance() - il exige que la classe a un constructeur par défaut public), alors vous avez un objet de classe, sur laquelle vous pouvez appeler foo():

Class<Dummy> clazz = super.getEntity(); 
try { 
    Dummy d = clazz.newInstance(); 
    d.foo(); 
} catch (...) { 
} 

Notes:

  • depuis getEntity() est générique, il retourne le type de classe appropriée, donc la distribution de Class<Dummy> n'est pas nécessaire,
  • Class.newInstance() peut jeter diverses exceptions qui y Vous devez gérer, d'où le bloc try-catch. C'est l'une des raisons pour lesquelles la réflexion n'est pas un moyen privilégié de résoudre de tels problèmes, puisque dans la classe dérivée vous connaissez le paramètre de type exact utilisé dans la classe de base, ce code est inutilement verbeux et plutôt artificiel.

Alternativement, vous pouvez préférer le retour T de getEntity() au lieu de Class<T> - cette façon, vous pouvez appeler foo() directement sur l'objet retourné. Notez que puisque vous ne pouvez pas instancier directement des types génériques, vous devez passer une instance de la classe à la superclasse (par exemple en tant que paramètre constructeur, ou via une méthode virtuelle substituée) ou la créer en utilisant la réflexion décrite ci-dessus.

Voici comment le faire en utilisant un paramètre constructeur:

public abstract class ABC<T> { 
    private T dummy; 
    public ABC(T dummy) { this.dummy = dummy; } 
    ... 
    public T getEntity() { return dummy; } 

} 

public class DEF extends ABC<Dummy> { 
    public DEF() { 
    super(new Dummy(); } 
    } 
    public void doSomething() { 
    Dummy dummy = getEntity(); 
    dummy.foo(); 
    } 
} 
+0

dummy est instancié dans le constructeur, public abstrait ABC { – user440719

+0

dummy est instancié dans le constructeur, public abstract ABC {public ABC (Classe dummy) {this.dummy = dummy; } ...} Si dummy n'est pas une instance, comment puis-je obtenir une référence à son instance? – user440719

+0

@staley, voir mon exemple de code. –

Questions connexes