Frage

Wie kann ich die die übergeordnete Klasse einer Klasseninstanz in Java ME erhalten. Das heißt, fälscht die Class.getSuperclass () Funktionalität mit eingeschränkter Funktionalität zur Verfügung in CLDC 1.1?

Was soll ich tun, ist die abstrakte Superklasse zu lassen, etwas tun, wie folgt aus:

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;
  }
}

Unterklassen könnten dann Spezialisierungen hinzufügen wie folgt aus:

 public Styler createStylerForViewClass(Class clazz) {
   if (clazz == SpecialView.class) {
     return new SpecialStyler();
   } else {
     return super.createSylerForViewClass(clazz);
   }
 }
War es hilfreich?

Lösung

Wie Sie vielleicht schon entdeckt haben, MIDP stellt kein Verfahren für die übergeordnete Klasse einer Klasse immer noch für alle Klassen in der Anwendung aufzählt.

Also alles, können Sie tun, ist der Überblick über die Klassenhierarchie selbst.

eine gemeinsame übergeordnete Klasse macht es etwas einfacher, weil man seine eigene Klasse hat das neue Objekt hinzufügen zu einer globalen Klasse Sammlung (falls nicht bereits vorhanden) in der Oberklassenkonstruktors:

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

aber leider nicht funktioniert für abstrakte Klassen, weil keine Instanzen je geschaffen werden.

Die Verfolgung der übergeordneten Klasse / Unterklasse Beziehungen für eine bekannte Untergruppe von Klassen ist einfach genug. z.

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;
}

Aber das kann „miss“ Zwischenklassen, die später hinzugefügt werden, z.B. Wenn Sie diese Klassen haben:

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

und Add A und C zu dem Baum und baten sie für die übergeordnete Klasse von C würde es gibt Sie A, und wenn Sie später B hinzugefügt würde es A als übergeordnete Klasse von C ersetzen, aber erst die falschen styler zurückgegeben worden sind für einige Instanzen von C.

Also ich denke, Sie werden die Einschränkung hinzufügen müssen, dass Vorfahren Klassen (die Styler definiert für sie) muss zuerst in den Baum eingefügt werden. Möglicherweise aus dem statischen Initialisierungsblocks der Klasse, die überschreibt createStylerForViewClass oder die statischen Initialisierer der Ansichtsklasse selbst.

Ich glaube an einen anderen bösen Hack, aber ich kann es nicht wirklich empfehlen:

  • Im View Konstruktor, erstellen Sie eine neue Exception, aber nicht werfen.
  • Zur Zeit Swap System.err für Ihre eigenen Schriftsteller, dass Schreiben in einem ByteArrayOutputStream
  • Anruf printStackTrace() auf die Ausnahme
  • Wiederherstellen System.err auf den ursprünglichen Wert
  • Parse die Stack-Trace aus dem ByteArrayOutputStream. Die Namen der Zwischenklassen Konstrukteurs werden in dem Stack-Trace sein. Jetzt können Sie sie nachschlagen Class.forName() mit und fügen Sie sie in den Baum.

Andere Tipps

Sie haben zwei Möglichkeiten:

Wenn Sie wissen, dass die Super-Klasse auf einen begrenzten Satz gehört, können Sie einfach Instanceof nennen oder die Class.isInstance () Methode.

Alternativ können Sie einen Präprozessor auf Sie Code auszuführen und eine Datenstruktur zu erstellen, die separat gespeichert wird, die Ihre Klassen Informationen hält. Wahrscheinlich sogar eine benutzerdefinierte doclet Dose Tu es. Der Ausgang kann ein Text oder Binär-Datei sein, die die Struktur beschreibt:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

Beachten Sie Problem mit der Verschleierung auf diese Weise haben können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top