2010-01-20 6 views
3

Java ME에서 Class 인스턴스의 수퍼 클래스를 가져 오는 방법은 무엇입니까? 즉, CLDC 1.1에서 사용할 수있는 제한된 기능으로 Class.getSuperclass() 기능을 위조합니까? 당신은 두 가지 옵션이 있습니다Java ME에서 Class.getSuperclass() 대체?

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를 추가 한 경우는 C의 슈퍼 클래스로 A을 대체 할 것이다 그러나 잘못된 스타일러가 C의 일부 인스턴스에 반환 될 때까지는 아닙니다.

그래서 선생님 클래스 (정의 된 스타일러가있는)를 먼저 트리에 추가해야한다는 제한을 추가해야한다고 생각합니다. 아마도 createStylerForViewClass을 재정의하는 클래스의 정적 초기화 프로그램 블록이나 뷰 클래스 자체의 정적 초기화 프로그램에서 가져온 것일 수 있습니다.

나는 다른 하나의 악을 해킹 생각 못했지만, 난 정말 추천 할 수 없습니다

  • View 생성자에서 새로운 Exception을 만들 수 있지만 그것을 던져하지 않습니다.
  • 일시적으로 ByteArrayOutputStream에서 스택 추적을 구문 분석 원래 값
  • 에 예외
  • ByteArrayOutputStream
  • 전화 printStackTrace()에 글을 자신의 작가 복원 System.err에 대한 System.err을 교환합니다. 중간 클래스 생성자의 이름은 스택 추적에 포함됩니다. 이제 Class.forName()을 사용하여 검색 한 다음 트리에 추가 할 수 있습니다.
+0

함께 사용해도 충분합니다. 모든 뷰 서브 클래스가'registerClass (MyClass.class)'를 정적 이니셜 라이저로 호출 할 것을 요구합니다. 시행하기 어렵지만 충분히 좋습니다. CLDC에서'final'이라면'System.err' 이후로 추한 해킹이 불가능합니다. ( – PeyloW

+0

) J2ME에서 스택 추적을 얻는 표준 방법이 없습니다. 에뮬레이터를 사용하거나 Symbian 전화 및 "redirect : //"GCF 프로토콜을 사용하십시오. –

1

:

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

서브 클래스는 다음과 같은 전문을 추가 할 수 있습니다

는 내가 뭘 원하는 추상 슈퍼 클래스는 같은 것을 할 수 있도록하는 것입니다

슈퍼 클래스가 제한된 세트에 속한다는 것을 알고 있으면 instanceof를 호출하거나 Class.isInstance() 메서드를 사용할 수 있습니다.

또는 코드를 실행하고 별도로 저장되어 클래스 정보를 보유하는 데이터 구조를 만들 수있는 전처리기를 가질 수 있습니다. 아마 심지어 주문 doclet 그것을 할 수 있습니다.

ClassA:SuperClass 
ClassB:AnotherSuperClass 
etc. 

공지 사항이 방법으로 난독에 문제가있을 수 있습니다 : 출력 구조를 설명하는 텍스트 또는 바이너리 파일이 될 수 있습니다.

+0

개인적으로 나는'instanceof' 연산자를 고수하고 제한된 클래스 집합을 사용하려고 노력할 것입니다. 나는 당신이 코드를 더 애매하게 만들 수 있기 때문에 전처리기를 사용하는 것을 정말로 좋아하지 않는다. – Malcolm

+0

나는 텍스트를 조작하기 위해 전처리기를 사용하지 않았다. 설명을 위해 응답을 참조하십시오. –

+0

프레임 워크를 구현할 때부터 수퍼 클래스가 무엇인지 알 수 없습니다. 나는 스타일러스 고객이 사용하고자하는 것을 통제 할 수 없다. 나는 주어진 클래스에 대해 올바른 스타일러를 가져 오기위한 유연하고 게으른 로딩 메소드를 만들고 싶다. – PeyloW

관련 문제