Pregunta

¿Cómo puedo conseguir el la superclase de una instancia de clase en Java ME. Es decir, la funcionalidad falsa Class.getSuperclass () con la funcionalidad limitada disponible en CLDC 1.1?

Lo que quiero hacer es dejar que la superclase abstracta hacer algo como esto:

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

clases Sub entonces podría añadir especializaciones como esto:

 public Styler createStylerForViewClass(Class clazz) {
   if (clazz == SpecialView.class) {
     return new SpecialStyler();
   } else {
     return super.createSylerForViewClass(clazz);
   }
 }
¿Fue útil?

Solución

Como ya se ha descubierto, MIDP no proporciona un método para conseguir la superclase de una clase, ni para enumerar todas las clases de la aplicación.

Así que todo lo que puede hacer es no perder de vista la jerarquía de clases usted mismo.

Tener una superclase común hace que sea un poco más fácil, ya que se puede tener el nuevo objeto de añadir su propia clase a una colección de clase mundial (si no está ya presente) en el constructor de la superclase:

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

pero por desgracia esto no funcionará para las clases abstractas, porque no hay casos se han creado.

Hacer un seguimiento de las relaciones superclase / subclase para un subconjunto conocido de clases es bastante fácil. por ejemplo:.

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

Sin embargo, esto puede "miss" clases intermedias que se agregan más tarde, por ejemplo, Si usted tiene estas clases:

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

y A complemento y C al árbol y se les pidió que para la superclase de C que le daría A, y si después se agregaban B que reemplazaría A como la superclase de C, pero no hasta que había sido devuelto el moldeador mal para algunos casos de C.

Así que creo que tendrá que añadir la restricción de que los ancestros clases (que tienen stylers definidos para ellos) deben ser añadidos al árbol en primer lugar. Posiblemente de la estática inicializador bloque de la clase que anula createStylerForViewClass, o la estática inicializador de la propia clase de vista.

Me hizo pensar en otro truco mal, pero no puedo realmente recomiendo:

  • En el constructor View, crear un nuevo Exception, pero no lo tire.
  • Temporalmente System.err de intercambio para su propio escritor que escribe en un ByteArrayOutputStream
  • printStackTrace() llamada en la excepción
  • Restaurar System.err a su valor original
  • Analizar el seguimiento de pila de la ByteArrayOutputStream. Los nombres de los constructores de las clases intermedias estarán en el seguimiento de la pila. Ahora se puede mirar hacia arriba usando Class.forName() y añadirlos al árbol.

Otros consejos

Existen dos opciones:

Si sabe que la super clase pertenece a un grupo limitado, sólo puede llamar a instanceof o utilizar el Class.isInstance () método.

Como alternativa, puede tener un preprocesador para funcionar con su código y crear una estructura de datos que se guarda por separado que contiene la información de clases. Probablemente incluso una costumbre doclet lata hazlo. La salida puede ser un texto o un archivo binario que describe la estructura:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

Aviso que puede tener un problema con la ofuscación de esta manera.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top