2010-06-29 5 views
6

Dans mon code a ont les superclasse abstraites suivantUtiliser un type générique d'une sous-classe dans sa superclasse abstraite?

public abstract class AbstractClass<Type extends A> {...} 

et certaines classes d'enfants comme

public class ChildClassA extends AbstractClass<GenericTypeA> {...} 

public class ChildClassB extends AbstractClass<GenericTypeB> {...} 

Je cherche une façon élégante comment je peux utiliser le type générique des classes d'enfants (GenericTypeA, GenericTypeB, ...) dans la classe abstraite de manière générique.

Pour résoudre ce problème, je actuellement défini la méthode

protected abstract Class<Type> getGenericTypeClass(); 

dans ma classe abstraite et mis en œuvre la méthode

@Override 
protected Class<GenericType> getGenericTypeClass() { 
    return GenericType.class; 
} 

dans toutes les classes d'enfants.

Est-il possible d'obtenir le type générique des classes enfants dans ma classe abstraite sans implémenter cette méthode auxiliaire?

BR,

Markus

Répondre

10

Je pense que c'est possible. J'ai vu que cela était utilisé dans les modèles DAO avec les génériques. par exemple. Tenir compte des classes:

public class A {} 
public class B extends A {} 

Et votre classe générique:

import java.lang.reflect.ParameterizedType; 
    public abstract class Test<T extends A> { 

    private Class<T> theType; 

    public Test() { 
     theType = (Class<T>) (
       (ParameterizedType) getClass().getGenericSuperclass()) 
       .getActualTypeArguments()[0]; 
    } 

    // this method will always return the type that extends class "A" 
    public Class<T> getTheType() { 
     return theType; 
    } 

    public void printType() { 
     Class<T> clazz = getTheType(); 
     System.out.println(clazz); 
    } 
    } 

Vous pouvez avoir une classe Test1 qui étend test avec la classe B (il extends A)

public class Test1 extends Test<B> { 

    public static void main(String[] args) { 
     Test1 t = new Test1(); 

     Class<B> clazz = t.getTheType(); 

     System.out.println(clazz); // will print 'class B' 
     System.out.println(printType()); // will print 'class B' 
    } 
    } 
+0

Je ne comprends pas ce que le code dans le constructeur de Test fait vraiment, mais cela a fonctionné. Maintenant, je n'ai plus besoin d'utiliser les méthodes d'aide. Merci :-) – Markus

+2

Il utilise la réflexion.Premièrement, il obtient la superclasse générique (java.lang.reflect.Type) de la classe, dans notre cas il ne sera jamais nul et nous savons qu'il s'agit d'un ParameterizedType, donc nous le castons et appelons la méthode getActualTypeArguents qui retourne un tableau de les arguments de type réels, par exemple B, du type. – naikus

+0

Ahhh, merci pour votre explication. – Markus

0

Je ne suis pas sûr que je comprends parfaitement votre question - <Type>est le type générique de la sous-classe, même quand il est exprimée dans la classe abstraite. Par exemple, si votre résumé superclasse définit une méthode:

public void augment(Type entity) { 
    ... 
} 

et vous instancier un ChildClassA, vous ne serez en mesure d'appeler augment avec une instance de GenericTypeA. Maintenant, si vous voulez un littéral de classe, alors vous devrez fournir la méthode comme vous l'avez indiqué. Mais si vous voulez juste le paramètre générique, vous n'avez rien de spécial à faire.

+0

Désolé, je ne Tu n'as pas vraiment compris. Type est étendu par les types génériques des sous-classes. Par conséquent, il est possible de renvoyer le type de la sous-classe à Type et de l'utiliser dans la super classe abstraite. – Markus

+0

@Markus - Maintenant * Je * ne comprends pas votre deuxième phrase, je ne pense pas que ce soit logique. Vous ne pouvez pas lancer de paramètre de type dans un sens quelconque; dans la (les) définition (s) de classe, il s'agit simplement d'un espace réservé pointant sur le type avec lequel vous créez réellement un objet. Et les sous-classes ne * étendent * pas le type, elles fournissent une limite concrète pour cela. Ainsi, lorsque les méthodes de 'AbstractClass' sont appelées pour une instance de' ChildClassA', 'type' ** est **' GenericTypeA'. –

Questions connexes