web-dev-qa-db-fra.com

Obtenir le nom d'une sous-classe à partir d'une super-classe

Disons que j'ai une classe de base nommée Entity. Dans cette classe, j'ai une méthode statique pour récupérer le nom de la classe:

class Entity {
    public static String getClass() {
        return Entity.class.getClass();
    }
}

Maintenant, j'ai une autre classe étendre ça.

class User extends Entity {
}

Je veux obtenir le nom de la classe de l'utilisateur:

System.out.println(User.getClass());

Mon objectif est de voir la sortie "com.packagename.User" sur la console, mais je vais plutôt me retrouver avec "com.packagename.Entity" car la classe Entity est référencée directement à partir de la méthode statique.

Si ce n'était pas une méthode statique, cela pourrait facilement être résolu en utilisant le mot clé this dans la classe Entity (c'est-à-dire: return this.class.getClass()). Cependant, j'ai besoin de cette méthode pour rester statique. Des suggestions sur la façon d'aborder cela?

61
Matt Huggins

Pas possible. Les méthodes statiques ne sont en aucun cas polymorphes à l'exécution. Il est absolument impossible de distinguer ces cas:

System.out.println(Entity.getClass());
System.out.println(User.getClass());

Ils compilent le même code d'octet (en supposant que la méthode est définie dans Entity).

En outre, comment appelleriez-vous cette méthode de manière à ce qu’elle soit logique de la rendre polymorphe?

39
Michael Borgwardt

Ne pas rendre la méthode statique. Le problème est que lorsque vous appelez getClass(), vous appelez la méthode dans la super classe - les méthodes statiques ne sont pas héritées. En outre, vous surveillez le nom Object.getClass(), ce qui prête à confusion. 

Si vous devez vous connecter le nom de la classe dans la superclasse, utilisez

return this.getClass().getName();

Cela renverra "Entity" lorsque vous avez une instance Entity, "User" lorsque vous avez une instance User, etc.

80
matt b

Votre question est ambiguë mais, autant que je sache, vous voulez connaître la classe actuelle à l'aide d'une méthode statique. Le fait que les classes héritent les unes des autres n’a aucune importance, mais pour les besoins de la discussion, je l’ai implémenté également.

 class Parent {
 public static void printClass () {
 System.out.println (Thread.currentThread (). GetStackTrace () [2] .getClassName ()); 
 } 
} 

 public class Test étend Parent {
 public static void main (String [] args) {
 printClass (); 
 } 
} 
6
Gilead

Ça marche pour moi

this.getClass().asSubclass(this.getClass())

Mais je ne suis pas sûr de savoir comment cela fonctionne bien.

5
sirolf2009

La superclasse ne devrait même pas connaître l'existence de la sous-classe, encore moins effectuer des opérations en fonction du nom complet de la sous-classe. Si vous avez besoin d'opérations basées sur la classe exacte et que vous ne pouvez pas exécuter la fonction nécessaire par héritage, vous devez procéder comme suit:

public class MyClassUtil
{
    public static String doWorkBasedOnClass(Class<?> clazz)
    {
        if(clazz == MyNormalClass.class)
        {
            // Stuff with MyNormalClass
            // Will not work for subclasses of MyNormalClass
        }

        if(isSubclassOf(clazz, MyNormalSuperclass.class))
        {
            // Stuff with MyNormalSuperclass or any subclasses
        }

        // Similar code for interface implementations
    }

    private static boolean isSubclassOf(Class<?> subclass, Class<?> superclass)
    {
        if(subclass == superclass || superclass == Object.class) return true;

        while(subclass != superclass && subclass != Object.class)
        {
            subclass = subclass.getSuperclass();
        }
        return false;
    }
}

(Code non testé)

Cette classe ne connaît pas non plus ses propres sous-classes, mais utilise plutôt la classe Class pour effectuer des opérations. Très probablement, cela restera étroitement lié aux implémentations (généralement une mauvaise chose, ou si ce n’est pas mal, ce n’est pas spécialement bien ), mais je pense qu’une telle structure est meilleure qu’une super-classe qui détermine ce que tous ses les sous-classes sont.

3
Brian S

Pourquoi voulez-vous implémenter votre propre méthode getClass ()? Vous pouvez simplement utiliser

System.out.println(User.class);

Edit (pour élaborer un peu): Vous voulez que la méthode soit statique. Dans ce cas, vous devez appeler la méthode sur la classe dont vous voulez nommer la classe, que ce soit la sous-classe ou la super-classe. Ensuite, au lieu d'appeler MyClass.getClass(), vous pouvez simplement appeler MyClass.class ou MyClass.class.getName().

En outre, vous créez une méthode static avec la même signature que la méthode d'instance Object.getClass(), qui ne sera pas compilée.

2
samitgaur
  1. Créez une variable membre membre dans la superclasse.
  2. Ajoutez this.getClass (). GetName () à un constructeur qui stocke la valeur dans la variable membre String.
  3. Créez un getter pour renvoyer le nom.

Chaque fois que la classe étendue est instanciée, son nom sera stocké dans la chaîne et accessible avec le getter.

2
Dawg 'N IT

Mon contexte: superclasse Entité avec sous-classes pour objets XML . Ma solution: Créer une variable de classe dans la superclasse.

Class<?> claz;

Ensuite, dans la sous-classe, je définirais la variable de la superclasse dans le constructeur

public class SubClass {
   public SubClass() {
     claz = this.getClass();
   }
}
0
Matthias dirickx

Une méthode statique est associée à une classe et non à un objet spécifique. 

Considérez comment cela fonctionnerait s'il y avait plusieurs sous-classes - par exemple, l'administrateur est également une entité. Comment votre méthode statique Entity, associée uniquement à la classe Entity, pourrait-elle savoir quelle sous-classe vous vouliez?

Vous pourriez:

  • Utilisez la méthode getClass () existante.
  • Passez un argument à votre méthode statique getClass () et appelez une méthode d'instance sur cet objet.
  • Rendez votre méthode non statique et renommez-la.
0
Andy Thomas

Si je comprends bien votre question, je pense que la seule façon de réaliser ce que vous voulez est de réimplémenter la méthode statique dans chaque sous-classe, par exemple:

class Entity {
    public static String getMyClass() {
        return Entity.class.getName();
    }
}

class Derived extends Entity {
    public static String getMyClass() {
        return Derived.class.getName();
    }
}

Cela imprimera package.Entity et package.Derived selon vos besoins. Sale mais bon, si ce sont tes contraintes ...

0
brabster

Si je le prends bien, vous voulez utiliser votre sous-classe dans la classe de base de la méthode statique .__ Je pense que vous pouvez le faire en passant un paramètre de classe à la méthode

class Entity {
    public static void useClass(Class c) {
        System.out.println(c);
        // to do code here
    }
}

class User extends Entity {
}

class main{
    public static void main(String[] args){
        Entity.useClass(Entity.class);
    }
}
0
Dis Honest