2010-01-20 6 views
3

Как я могу получить суперкласс класса экземпляра в Java ME. То есть поддельные функции Class.getSuperclass() с ограниченной функциональностью, доступной в CLDC 1.1?Class.getSuperclass() замена на Java ME?

То, что я хочу сделать, это позволить абстрактный класс супер сделать что-то вроде этого:

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 классы могли затем добавить специализаций, как это:

public Styler createStylerForViewClass(Class clazz) { 
    if (clazz == SpecialView.class) { 
    return new SpecialStyler(); 
    } else { 
    return super.createSylerForViewClass(clazz); 
    } 
} 
+0

Есть ли общий суперкласс для всех классов вида? И будут ли эти методы ('createStylerForViewClass' и' getStylerForViewClass') принадлежать этому суперклассу? Если да, то почему требуется параметр 'clazz'? – finnw

+0

Да, у них есть общий суперкласс, но вы не будете применять эти методы. Просто вызовите getStylerForViewClass() со своим собственным классом, чтобы получить для них наиболее подходящий стилист. – PeyloW

ответ

1

Как вы уже обнаружили, MIDP не предоставляет метод для получения суперкласса класса или для перечисления всех классов в приложении.

Итак, все, что вы можете сделать, это следить за иерархией классов самостоятельно.

Имея общий суперкласс делает его немного легче, потому что вы можете иметь новый объект добавить свой собственный класс в глобальную коллекцию класса (если уже нет) в конструктора суперкласса:

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

, но к сожалению, это не будет работать для абстрактных классов, потому что экземпляры никогда не создаются.

Отслеживание отношений суперкласса/подкласса для известного подмножества классов достаточно просто. например,

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

Но это может «пропустить» промежуточные классы, которые добавляются позже, например. если у вас есть эти классы:

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

и добавить A и C к дереву и попросил его суперкласс C это даст вам A, и если вы позже добавил B он заменит A как суперкласс C , но только до тех пор, пока неправильный стайлер не был возвращен для некоторых случаев C.

Поэтому я думаю, вам нужно будет добавить ограничение, согласно которому классы-предшественники (которые имеют стили, определенные для них) должны быть добавлены в дерево сначала. Возможно, из статического блока инициализатора класса, который переопределяет createStylerForViewClass или статический инициализатор самого класса представления.

Я думаю, что одной другой злой рубить, но я не могу рекомендовать его:

  • В View конструктор, создать новый Exception, но не бросать его.
  • Временно поменять System.err для своего собственного писателя, который пишет в ByteArrayOutputStream
  • Зов printStackTrace() на исключение
  • Восстановление System.err к исходному значению
  • Разбираем трассировки стека из ByteArrayOutputStream. Имена конструкторов промежуточных классов будут в трассировке стека. Теперь вы можете посмотреть их, используя Class.forName() и добавить их в дерево.
+0

Достаточно хорошо для работы. Я думаю, что мне потребуется, чтобы все подклассы View вызывали 'registerClass (MyClass.class)' как статический инициализатор. Трудно обеспечить соблюдение, но достаточно хорошо. Уродливый хак не оправдан, так как 'System.err', если' final' в CLDC, я уже рассматривал это также :(. – PeyloW

+0

Нет стандартного способа получить трассировку стека в J2ME. эмулятор или использовать телефон Symbian и его протокол «перенаправления: //» GCF. –

1

У вас есть два варианта:

Если вы знаете, что суперкласс принадлежит ограниченному набору, вы можете просто вызвать instanceof или использовать метод Class.isInstance().

В качестве альтернативы вы можете иметь препроцессор для запуска кода и создать структуру данных, которая сохраняется отдельно, которая хранит информацию о ваших классах. Вероятно, это может сделать даже обычай doclet. Выход может быть текстовый или двоичный файл, который описывает структуру:

ClassA:SuperClass 
ClassB:AnotherSuperClass 
etc. 

Обратите внимание, вы можете иметь проблемы с запутывания таким образом.

+0

Лично я бы попытался придерживаться оператора 'instanceof' и попытаться использовать ограниченный набор классов. Мне не очень нравится использование препроцессоров, поскольку они могут сделать ваш код более неясным. – Malcolm

+0

Я не хотел использовать препроцессор для манипулирования текстом. См. Ответ для уточнения. –

+0

Я не могу знать, что такое суперклассы, поскольку я реализую фреймворк. Я не контролирую, какие клиенты стайлеров хотят использовать. Я просто хочу создать гибкий и ленивый способ загрузки для получения правильного стилиста для любого заданного класса. – PeyloW