Question

Comment puis-je obtenir le superclasse d'une instance de classe en Java ME. C'est, la fonctionnalité faux Class.getSuperclass () avec la fonctionnalité limitée disponible dans CLDC 1.1?

Ce que je veux faire est de laisser la classe abstraite super de faire quelque chose comme ceci:

public Styler getStylerForViewClass(Class clazz) {
   Styler s = stylers.get(clazz);
   if (s == null) {
     for (Class c = clazz; s == null; c = c.getSuperclass()) {
       if (c == Object.class) {
         throw new IllegalArgumentException("No Styler for " + clazz.getName());
       }
       s = createStylerForViewClass(c);
     }
     stylers.put(clazz, s);
   }
   return s;
}
public Styler createStylerForViewClass(Clazz clazz) {
  if (clazz == View.class) {
    return new DefaultStyler();
  } else {
    return null;
  }
}

sous-classes pourraient alors ajouter des spécialisations comme ceci:

 public Styler createStylerForViewClass(Class clazz) {
   if (clazz == SpecialView.class) {
     return new SpecialStyler();
   } else {
     return super.createSylerForViewClass(clazz);
   }
 }
Était-ce utile?

La solution

Comme vous l'avez déjà découvert, MIDP ne fournit pas une méthode pour obtenir la superclasse d'une classe, ni pour toutes les classes dans l'énumération de l'application.

Donc tout ce que vous pouvez faire est de garder une trace de la hiérarchie des classes vous.

Avoir une superclasse commune rend un peu plus facile, parce que vous pouvez avoir le nouvel objet ajouter sa propre classe à une collection de classe mondiale (si pas déjà) dans le constructeur superclasse:

abstract class View {
    protected View() {
        classHierarchy.add(this.getClass());
    }
}

mais malheureusement cela ne fonctionnera pas pour les classes abstraites, car aucune instance ne jamais créé.

Le suivi des relations superclasse / sous-classe pour un sous-ensemble connu des classes est assez facile. par exemple:.

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public class ClassHierarchy {
 public ClassHierarchy() {
  childToParentMap = new Hashtable();
  parentToChildMap = new Hashtable();
  parentToChildMap.put(Object.class, new Vector());
 }

 public boolean addClass(Class toAdd) {
  if (toAdd.isInterface()) return false;
  if (toAdd.equals(Object.class)) return false;
  if (childToParentMap.get(toAdd) != null) return false;

  addClassBelow(toAdd, Object.class, new Vector());
  return true;
 }

 public Class getParent(Class subclass) {
  return (Class) childToParentMap.get(subclass);
 }

 private void addClassBelow(Class toAdd, Class parent, Vector initialChildren) {
  Vector children = (Vector) parentToChildMap.get(parent);
  Class reparented;
  do {
   reparented = null;
   for (Enumeration childEnum = children.elements();
        childEnum.hasMoreElements();
        ) {
    Class child = (Class) childEnum.nextElement();
    if (child.isAssignableFrom(toAdd)) {
     addClassBelow(toAdd, child, initialChildren);
     return;
    } else if (toAdd.isAssignableFrom(child)) {
     children.removeElement(child);
     initialChildren.addElement(child);
     childToParentMap.put(child, toAdd);
     // Guard against concurrent modification
     reparented = child;
     break;
    }
   }
  } while (reparented != null);

  children.addElement(toAdd);
  childToParentMap.put(toAdd, parent);
  parentToChildMap.put(toAdd, initialChildren);
 }


 private Hashtable childToParentMap;

 private Hashtable parentToChildMap;
}

Mais cela peut « manquer » les classes intermédiaires qui sont ajoutés plus tard, par exemple si vous avez ces classes:

Object >= View >= A >= B >= C

et ajouter A et C à l'arbre et lui a demandé pour la superclasse de C il vous donnera A, et si plus tard ajouté B il remplacerait A comme superclasse de C, mais pas jusqu'à ce que le mal Styler avait été retourné pour certains cas de C.

Alors, je pense que vous devrez ajouter la restriction que l'ancêtre des classes (qui ont stylers définies pour eux) doit être ajouté à l'arbre d'abord. Peut-être à partir du bloc d'initialisation statique de la classe qui remplace createStylerForViewClass, ou l'initialisation statique de la classe d'affichage lui-même.

Je ne pensais d'un autre bidouille mal, mais je ne peux pas recommander vraiment:

  • Dans le constructeur de View, créez un nouveau Exception, mais ne le jetez pas.
  • échanger temporairement System.err pour votre propre écrivain qui écrit à un ByteArrayOutputStream
  • Appel printStackTrace() à l'exception
  • Restaurer System.err à sa valeur initiale
  • Parse la trace de pile de la ByteArrayOutputStream. Les noms des constructeurs de classes intermédiaires seront dans la trace de la pile. Maintenant, vous pouvez les rechercher à l'aide Class.forName() et les ajouter à l'arbre.

Autres conseils

Vous avez deux options:

Si vous savez que la classe super appartient à un ensemble limité, vous pouvez simplement appeler instanceof ou utiliser le Class.isInstance () .

Vous pouvez avoir un préprocesseur pour fonctionner sur votre code et créer une structure de données sauvegardées séparément qui contient les informations de vos classes. Probablement même une coutume doclet peut fais le. La sortie peut être un texte ou d'un fichier binaire qui décrit la structure:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

Notez que vous pouvez avoir des problèmes avec l'obscurcissement de cette façon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top