Как вы уже обнаружили, 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()
и добавить их в дерево.
Есть ли общий суперкласс для всех классов вида? И будут ли эти методы ('createStylerForViewClass' и' getStylerForViewClass') принадлежать этому суперклассу? Если да, то почему требуется параметр 'clazz'? – finnw
Да, у них есть общий суперкласс, но вы не будете применять эти методы. Просто вызовите getStylerForViewClass() со своим собственным классом, чтобы получить для них наиболее подходящий стилист. – PeyloW