Как вы уже обнаружили, MIDP не предоставляет метод для получения суперкласса класса или для перечисления всех классов в приложении.
Так что все, что вы можете сделать, - это самостоятельно отслеживать иерархию классов.
Наличие общего суперкласса делает его немного легче, потому что вы можете сделать так, чтобы новый объект добавил свой собственный класс в коллекцию глобальных классов (если она еще не существует) в конструкторе суперкласса:
abstract class View {
protected View() {
classHierarchy.add(this.getClass());
}
}
но, к сожалению, это не будет работать для абстрактных классов, потому что экземпляры никогда не создаются.
Отслеживание отношений суперкласса / подкласса для известного подмножества классов достаточно просто. e.g.:
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()
и добавлять их в дерево.