Domanda

Come posso ottenere la superclasse di un'istanza di classe in Java ME. Cioè, finta la funzionalità Class.getSuperclass () con la funzionalità limitate disponibili in CLDC 1.1?

Quello che voglio fare è quello di lasciare che la superclasse astratta fare qualcosa di simile:

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

classi Sub potrebbero poi aggiungere specializzazioni in questo modo:

 public Styler createStylerForViewClass(Class clazz) {
   if (clazz == SpecialView.class) {
     return new SpecialStyler();
   } else {
     return super.createSylerForViewClass(clazz);
   }
 }
È stato utile?

Soluzione

Come avete già scoperto, MIDP non fornisce un metodo per ottenere la superclasse di una classe, nè per enumerare tutte le classi nell'applicazione.

Quindi tutto quello che puoi fare è tenere traccia della gerarchia delle classi da soli.

Avere una superclasse comune rende leggermente più facile, perché si può avere il nuovo oggetto aggiungere la propria classe per una collezione di classe mondiale (se non è già presente) nella costruzione della superclasse:

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

, ma purtroppo questo non funziona per le classi astratte, perché non esistono istanze vengono mai creato.

Tenere traccia delle relazioni superclasse / sottoclasse per un sottoinsieme noto di classi è abbastanza facile. per esempio:.

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

Ma questo può "perdere" classi intermedie che vengono aggiunti in seguito, ad esempio se si dispone di queste classi:

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

e aggiungere A e C per l'albero e ha chiesto per la superclasse di C darebbe A, e se in seguito aggiunto B sostituirebbe A come superclasse di C, ma non fino a quando la styler sbagliata era stato restituito per alcuni casi di C.

Quindi penso che si dovrà aggiungere la restrizione che antenato classi (che hanno styler definiti per loro) devono essere aggiunti alla struttura ad albero prima. Possibilmente dal blocco statico inizializzatore della classe che sostituisce createStylerForViewClass, o l'inizializzatore statico della classe stessa vista.

ho pensato a un altro trucco male, ma non posso davvero lo consiglio:

  • Nel costruttore View, creare un nuovo Exception, ma non gettarlo.
  • Temporaneamente scambiare System.err per il proprio scrittore che scrive a un ByteArrayOutputStream
  • Chiamata printStackTrace() sull'eccezione
  • Ripristina System.err al suo valore originale
  • Analizzare l'analisi dello stack dal ByteArrayOutputStream. I nomi dei costruttori delle classi intermedie saranno nella traccia dello stack. Ora potete guardare in alto usando Class.forName() e aggiungerli alla struttura ad albero.

Altri suggerimenti

Sono disponibili due opzioni:

Se si sa che la classe Super appartiene a una serie limitata, si può chiamare instanceof o utilizzare il Class.isInstance () metodo .

In alternativa, si può avere un preprocessore per eseguire su di voi il codice e creare una struttura di dati che viene salvato separatamente che contiene le informazioni di classi. Probabilmente anche una consuetudine doclet può fallo. L'uscita può essere un testo o file binario che descrive la struttura:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

Si noti si possono avere problemi con l'offuscamento in questo modo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top