Comme vous l'avez déjà découvert, MIDP ne fournit pas de méthode pour obtenir la super-classe d'une classe, ni pour énumérer toutes les classes de l'application.
Donc tout ce que vous pouvez faire est de garder une trace de la hiérarchie des classes vous-même.
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, ce ne fonctionnera pas pour les classes abstraites, car aucune instance n'est créée.
Garder la trace des relations superclasse/sous-classe pour un sous-ensemble connu de 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 vous avez ajouté plus tard B
il remplacerait A
comme superclasse de C
, mais pas avant que le mauvais styler ait été retourné pour certaines instances de C
.
Donc je pense que vous devrez ajouter la restriction que les classes d'ancêtres (qui ont des stylers définis pour eux) doivent être ajoutées à l'arbre en premier. Peut-être à partir du bloc d'initialisation statique de la classe qui remplace createStylerForViewClass
ou l'initialiseur statique de la classe de vue elle-même.
Je ne pensais d'un autre bidouille mal, mais je ne peux pas recommander vraiment:
- Dans le constructeur
View
, créez un nouveau Exception
, mais ne le jetez pas.
- temporairement permuter
System.err
pour votre propre écrivain qui écrit à un ByteArrayOutputStream
- Appel
printStackTrace()
à l'exception
- Restore
System.err
à sa valeur initiale
- Parse la trace de la pile de la
ByteArrayOutputStream
. Les noms des constructeurs des classes intermédiaires seront dans la trace de la pile. Maintenant, vous pouvez les rechercher en utilisant Class.forName()
et les ajouter à l'arbre.
Existe-t-il une super-classe commune à toutes les classes d'affichage? Et ces méthodes ('createStylerForViewClass' et' getStylerForViewClass') appartiennent-elles à cette superclasse? Si oui, pourquoi le paramètre 'clazz' est-il requis? – finnw
Oui, ils ont une super-classe commune, mais vous ne mettra pas en œuvre ces méthodes. Appelez simplement getStylerForViewClass() avec leur propre classe afin d'obtenir le style le plus approprié pour eux. – PeyloW