2013-02-15 5 views
0

트리처럼 보이는 큰 데이터 구조가 있습니다. 모든 트리 비헤이비어, 링크, 링크 해제, 탐색 등을 구현하는 루트 클래스 TreeElement가 있습니다. 트리 내의 실제 노드는 TreeElement 클래스의 특수 서브 클래스입니다. 주어진 부모 노드는 둘 이상의 자식 유형을 갖습니다. NodeTypeB는 C (및 기타)의 아이를 가지고있는 동안, 당신이 볼 수 있듯이다형성 트리에서 Java 제네릭 형식 매개 변수를 사용하는 방법

NodeTypeA 
+ NodeTypeB 
    + NodeTypeC 
    + NodeTypeC 
+ NodeTypeB 
    + NodeTypeC 
+ NodeTypeD 
    + NodeTypeE 

, NodeTypeA는 유형 B와 D (및 기타)의 자식이 : 다음은 샘플 나무입니다. NodeTypeD에는 E 형의 자식 (및 다른 자식도있을 수 있음)이 있습니다. 이 모든 것은 TreeElement의 서브 클래스입니다. 특수 하위 클래스에는 허용되는 자녀 유형에 대한 지식이 있습니다.

기본 유형 TreeElement이 모든 아이들로 가득 찬 벡터의 종류의 값으로 표시하고, 클래스의 전달 클래스로 지정 반환

Vector getChildren(String kind, Class nodeType); 

하는 방법이있다. 반환 된 벡터는 항상 포함됩니다 클래스의 요소가 전달되었습니다. 문제는 유형 안전성을 올바르게 구현하려는 것이고 Java의 동적 유형 지정 기능을 사용하는 방법이 명확하지 않습니다. 내가 위를 쓸 때, 나는 타입 캐스팅이 필요하다는 것을 Eclipse에서 경고를

Vector<NodeTypeB> getSpecialChildren() { 
    Vector<NodeTypeB> vb = getChildren("special", NodeTypeB.class); 
    return vb; 
} 

: 클래스 NodeTypeA에서

, 나는 NodeTypeB의 자녀를 얻을이 같은 방법을 싶습니다. 또한 "불필요한 캐스트를 제거"하는 이클립스의 기능이이 기능이 캐스트를 제거

Vector<NodeTypeB> getSpecialChildren() { 
    Vector<NodeTypeB> vb = (Vector<NodeTypeB>) getChildren("special", NodeTypeB.class); 
    return vb; 
} 

을하지만 : 그래서 타입 캐스트를 추가 할 수 있습니다. 이클립스가 불필요하다고 생각하는 것은 다소 이상하게 보입니다. 그러나 그것이 없으면 경고합니다. 그러나 그것은 단지 성가심 일뿐입니다.

정말로하고 싶은 것은이 작업을 올바르게 수행하기 위해 자바의 동적 유형 메카니즘 ('bounded type parameters'???)을 사용하는 것입니다. TreeElement 클래스에서 getChildren 메소드를 선언하여 전체 유형의 안전성을 갖춘이 메커니즘을 구현하는 방법을 알아낼 수 없습니다. 클래스 매개 변수를 제거한다고 가정합니다. 어떤 도움을 주시면 감사하겠습니다.

+0

나는 이것이 가능할 것으로 기대하지 않습니다.Java의 유형 시스템은 설명하는 구조에서 원하는 보장을하기에 충분하지 않습니다. 솔직히, 만약 내가 너라면, 나는 일반적인 "tree"타입에 적합하게 만들고 일반 클래스 구조로 이것을 수행하려는 시도를 포기할 것이다. - NodeTypeA는 오래된 클래스 일 뿐이며, 확장되지 않는다. 'List '및'List '필드가 있습니다. –

+0

getChildren 메서드는 원시 형식을 반환하므로이를 고치지 않고 컴파일러에서 보장하는 형식 안전성을 얻을 수있는 방법은 없습니다. – Affe

+0

@Affe - 정확히 묻는 질문입니다. getChildren 선언을 정확히 고치는 방법 – AgilePro

답변

1

getChildren의 선언을 해결하는 방법은 다음과 같습니다 사용할 때 컴파일러를 얻을 것이다

public <T extends TreeElement> Vector<T> getChildren(String string, Class<T> nodeType) 

는 유형 경고 곁을 떠날 수 있습니다.

제네릭은 컴파일 타임 기능이며 런타임 유형 인수를 제공하기 때문에 해당 메서드의 구현에는 여전히 경고가 표시되지만 경고는 적어도 해당 메서드 내에서 격리됩니다.

+0

다른 유형의 자녀가있는 경우 이것이 어떻게 작동 할 수 있는지는 명확하지 않습니다. –

+0

예를 들어이 메소드가 수행하는 것과 정확히 같은 방법은 다음과 같습니다. 'http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#createQuery(java.lang.String, java. 랭. 클래스)'? 실제 구현은 런타임에 컴파일되지 않는 런타임 유형 조작이지만 신뢰할 수있는 방법으로 서명을 그렇게 구성하여 신뢰하도록 컴파일러에 지시합니다. – Affe

+0

좋습니다, 기본적으로 작동했습니다! 그것은 내가 연구해야하는 코드베이스에 5 개의 오류를 일으킨다. 오류 중 하나는 메서드가 구체적인 클래스가 인터페이스를 구현하는 인터페이스 컬렉션을 반환해야하지만 오류가 발생하는 경우입니다. 그것이 다른 문제이기 때문에 나는이 질문/대답을 지금 당장 복잡하게 만들지 않을 것이고, 나는 그 답을 다른 곳에서 얻을 수 있는지 보게 될 것이다. – AgilePro

0

중첩 세트 트리 또는 인접 트리 중 하나의 구현을 고려해야합니다. 매우 유용하고 쉽게 용도가 변경되는 제네릭을 사용하는 중첩 세트 트리 용 클래스를 만들었습니다.

그것의 핵심은 같은 것을 볼 것입니다

:

public class NestedSetTree<? extends NestedSetTree<T>> 

그런 다음 노드 등 당신의 getParent(), getAncestorOfType (노드 종류 형) 등의 모든 기초를 구현할 수 있습니다 단지 T.이다

관련 문제