Pergunta

Como posso obter a superclasse de uma instância de classe em Java Me. Isto é, falsificar a funcionalidade da classe.getSuperclass () com a funcionalidade limitada disponível no CLDC 1.1?

O que eu quero fazer é deixar a super classe abstrata fazer algo assim:

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

Sub -classes podem então adicionar especializações como esta:

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

Solução

Como você já descobriu, o MIDP não fornece um método para obter a superclasse de uma classe, nem para enumerar todas as classes no aplicativo.

Então, tudo o que você pode fazer é acompanhar a hierarquia da classe.

Ter uma superclasse comum facilita um pouco, porque você pode ter o novo objeto adicionar sua própria classe a uma coleção de classes globais (se ainda não estiver presente) no construtor de superclasse:

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

Infelizmente, porém, isso não funcionará para classes abstratas, porque nenhuma instância foi criada.

Manter o controle das relações de superclasse/subclasse para um subconjunto de classes conhecido é fácil o suficiente. por exemplo:

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

Mas isso pode "perder" classes intermediárias que são adicionadas posteriormente, por exemplo, se você tiver essas aulas:

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

e adicione A e C para a árvore e pediu a superclasse de C Isso te daria A, e se você adicionou mais tarde B substituiria A como a superclasse de C, mas não até que o estilador errado tenha sido devolvido por alguns casos de C.

Então, acho que você terá que acrescentar a restrição de que as classes de ancestrais (que tenham estilistas definidas para eles) devem ser adicionadas primeiro à árvore. Possivelmente do bloco inicializador estático da classe que substitui createStylerForViewClass, ou o inicializador estático da própria classe de exibição.

Eu pensei em outro hack do mal, mas não posso recomendar:

  • No View construtor, crie um novo Exception, mas não jogue.
  • Troque temporariamente System.err Para seu próprio escritor que escreve para um ByteArrayOutputStream
  • Ligar printStackTrace() na exceção
  • Restaurar System.err ao seu valor original
  • Analisar o rastreamento da pilha do ByteArrayOutputStream. Os nomes dos construtores das classes intermediárias estarão no rastreamento da pilha. Agora você pode procurá -los usando Class.forName() e adicione -os à árvore.

Outras dicas

Você tem duas opções:

Se você sabe que a super classe pertence a um conjunto limitado, você pode apenas ligar para a instância ou usar o Class.isInsinStance () método.

Como alternativa, você pode ter um pré -processador para executar seu código e criar uma estrutura de dados salva separadamente, que mantém as informações das classes. Provavelmente até um costume Doclet pode fazer isso. A saída pode ser um texto ou arquivo binário que descreve a estrutura:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

Observe que você pode ter problemas com a ofuscação dessa maneira.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top