2011-01-05 2 views
1

각 레벨에 고유 한 오브젝트 유형이있는 Java의 트리 클래스를 작성해야합니다. 아래에 쓰여진 방식은 제네릭을 이용하지 않으며 중복 된 코드를 많이 만듭니다. 제네릭으로 이것을 작성하는 방법이 있습니까?각 레벨마다 고유 한 오브젝트 유형이있는 트리 클래스 작성

public class NodeB { 
    private String nodeValue; 
    //private List<NodeB> childNodes; 
    // constructors 
    // getters/setters 
} 

public class NodeA { 
    private String value; 
    private List<NodeB> childNodes; 
    // constructors 
    // getters/setters 
} 

public class Tree { 
    private String value; 
    private List<NodeA> childNodes; 
    // constructors 
    // tree methods 
} 
+0

지금은 제네릭처럼 보이지 않거나 템플릿이 적용됩니다. 정보를 더 주신다면 어떨까요? 여기에서 할 수있는 유일한 일은 인터페이스를 구현하거나 추상 기본 클래스에서 상속하는 것입니다. – Falmarri

+0

호기심에서 벗어나서 왜 이것을해야합니까? 숙제 문제입니까? – templatetypedef

+0

이 트리는 NodeB 수준 (2 단계)으로 디자인되어 있습니까? 그렇지 않으면 NodeC, NodeD ...가 발생할 것으로 예상합니까? –

답변

2

이것은 단순한 구현하지만, 일반적인 아이디어를 줄 수있을만큼 :

import java.util.Arrays; 
import java.util.Collections; 
import java.util.List; 

public class GenericNode { 

    public static abstract class AbstractNode<V, N> { 
     private V value; 
     private List<N> children; 

     public AbstractNode(V value, N... children) { 
      this.value = value; 
      this.children = children != null ? Arrays.asList(children) 
        : Collections.<N> emptyList(); 
     } 

     public V getValue() { 
      return value; 
     } 

     public List<N> getChildren() { 
      return children; 
     } 

     public int getNumberOfChildren() { 
      return children.size(); 
     } 

     @Override 
     public String toString() { 
      return value.toString() + "->" + children.toString(); 
     } 
    } 

    // leaf node type, ignore type of children 
    public static class NodeB extends AbstractNode<String, Object> { 

     public NodeB(String value, Object... nodes) { 
      super(value, nodes); 
     } 
    } 

    // example of typical node in the mid of tree 
    public static class NodeA extends AbstractNode<String, NodeB> { 
     public NodeA(String value, NodeB... nodes) { 
      super(value, nodes); 
     } 
    } 

    // top level node type 
    public static class Tree extends AbstractNode<String, NodeA> { 
     public Tree(String value, NodeA... nodes) { 
      super(value, nodes); 
     } 
    } 

    @SuppressWarnings({ "rawtypes", "unchecked" }) 
    public static <V, N extends AbstractNode> int getNodeCount(
      AbstractNode<V, N> node) { 
     int nodeCount = node.getChildren().size(); 
     for (N child : node.getChildren()) { 
      nodeCount += getNodeCount(child); 
     } 
     return nodeCount; 
    } 

    public static void main(String[] args) { 
     NodeB nodeB1 = new NodeB("Leaf node 1"); 
     NodeB nodeB2 = new NodeB("Leaf node 2"); 
     NodeA nodeA = new NodeA("Node with children", nodeB1, nodeB2); 
     NodeA emptyNodeA = new NodeA("Empty node"); 
     Tree tree = new Tree("Tree", nodeA, emptyNodeA); 
     System.out.println(tree); 
     System.out.println(1 + getNodeCount(tree)); 
    } 
} 

당신은 N을 만들 수 있으며 값 및/또는 어린이에 몇 가지 일반적인 작업을 호출 할 수 있도록 V 유형은 특정 인터페이스를 구현합니다.

편집 : 노드 수를 검색을위한 재귀 적 방법으로 업데이트 구현

1

이 "노드"에서 상속 모두를위한 이상적인 장소이지만, 심지어는 필요하지 않습니다. \

은 당신이 아마 원하는 것은 당신의 다른 클래스에 대한 참조를 포함하는 하나의 일반적인 "노드"개체입니다 (상속 전에 컴포지션 사용).

그 시점에서 각기 다른 클래스가 수행 할 수있는 작업이있을 것입니다 (그렇지 않은 경우 모두 동일한 데이터 구조에있는 이유는 무엇입니까?). 이러한 공통 기능을 사용하여 공통 인터페이스를 구현하도록하십시오. 노드 클래스는이 인터페이스에 위임 할 수 있거나 다른 클래스는이 인터페이스로 클래스를 추출하여 이에 대한 조치를 취할 수 있습니다.

이것은 무언가를 노드로 강제하는 것보다 낫습니다. 간단한 일을하고 잘하십시오.

--edit-- 난 정말 당신이 당신의 시나리오에 대해 아무것도 게시하지 않았기 때문에 당신 관련된 예제를 추가 할 수 없습니다.

다른 클래스 A, B * C가 있다고 가정 해 봅시다. 먼저 Object의 하위 클래스를 제외하고 모두 AT와 관련되어 있습니까? 인터페이스 "Iface"를 구현한다고 가정 해 봅시다. (그렇지 않으면, 당신은 단지 "개체"로 Iface는 대체 할 수 있지만, 이것은 정말 나쁜 디자인을 의미한다.)

을 어쨌든, 당신의 "노드"개체는 이제 하나의 object--

public class Node { 
    private List<node> children; 
    private Iface myObject; 
    ... setters, getters, tree implementation, tree navigation, related garbage... 
} 

이입니다 당신의 나무를 만드는데 충분합니다. 일을 더 원활하게하기 위해 할 수있는 한 가지 방법은 "노드가 Iface를 구현"하고 객체에 모든 호출을 위임하는 것입니다. Iface는이 먹고 (식품 foodtype) 메소드가 포함되어있는 경우 예를 들어, 노드는 Iface는를 구현하는 방법 할 수 : 그것이 포함 된 클래스가 있었다 것처럼

public void eat(Food foodtype) { 
    myObject.eat(foodtype); 
} 

이는 "노드"클래스 역할을 할 것입니다.

그런데 다른 좋은 아이디어는 myObject를 "private final"로 만들고 생성자에서 null이 아닌지 확인하는 것입니다. 그렇게하면 항상 그것이 설정되어 있고 위임 된 구성원 중 누구도 null 확인을 수행하지 않아야한다는 것을 알게됩니다.

+0

예를 들어 설명해 주시겠습니까? – user479576

0

제네릭이이 경우에 많은 도움이 될 것이라고 생각하지 않습니다. 트리의 각 레벨마다 다른 클래스를 갖는 대신. 자식이 있고 각 수준에 다른 클래스를 저장하는 노드 클래스는 어떻습니까? 그렇게하면 많은 중복을 제거 할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 그것은 하나의 클래스에서 계층 구조를 어떻게 표현할 것입니까? – user479576

+0

앞서 언급 한 것처럼 하나의 Node 클래스 만 사용합니다. NodeA 또는 Tree 클래스와 비슷하지만 String 이외의 객체 유형을 저장합니다. – jzd

0

나는 자바에 비교적 새로운 해요, 그래서 이것은 내가 잘 모르는 것 같아요 문제가있을 수도 있지만 적어도 간단한 수준에서 작동하는 것 같다 .

메인 노드 클래스를 정의하십시오.이 노드는 트리의 루트가 될 것입니다.

public class NodeA { 

private String _value; 
private ArrayList<NodeA> _children; 
private int _depth; 

public NodeA (String value, int depth) { 
    _value = value; 
    _children = new ArrayList<NodeA>(); 
    _depth = depth; 
} 

//probably want getters for _children and _value here 

//this makes a new child, with its type depending on the depth of the tree it will 
//be placed at. NodeB and NodeC will both inherit from NodeA 
public void add(String value) { 
    switch (_depth) { 
     case 0: 
      _children.add(new NodeB(value, _depth+1)); 
      break; 
     case 1: 
      _children.add(new NodeC(value, _depth+1)); 
      break; 
    } 
} 

add() 메소드는 지정된 값을 사용하여 노드에 대한 새 하위를 생성합니다. 트리의 루트를 깊이 0의 NodeA로 초기화하면 노드에 하위 항목을 추가 할 수 있으며 다음 레벨에 모든 NodeB가 있고 그 다음 NodeC가 모두 포함되도록 트리가 채워집니다. NodeB와 NodeC의 코드는 매우 간단하며 임의의 양의 노드 레벨을 생성하기 위해 복제 될 수 있습니다 (여기에는 그 코드가 있습니다).

public class NodeB extends NodeA { 

public NodeB(String value, int depth) { 
    super(value, depth); 
} 
//nothing else needed! 

NodeC의 코드는 C의 B 's의 명백한 대체를 제외하고는 동일합니다.

희망/도움이 당신이 원하는 답변입니다!

+0

유일한 문제는 하나 이상의 노드 유형 (예 : NodeX, NodeZ)을 추가 할 때마다 기본 클래스 (NodeA)를 업데이트해야한다는 것입니다. –

+0

좋은 지적. switch 문을 사용하는 대신 각 하위 클래스에서 재정의 된 add (addchild로 이름을 바꿔야 함)를 추가하는 것이 좋습니다. 그것은 _depth도 불필요하게 만들 것입니다. –

2

필요한 것은 Pair<A, B>입니다. 나무의 예 :

Pair<A, Pair<B, C>> 
Pair<Pair<A, B>, Pair<C, D>> 
Pair<Pair<Pair<A, B>, Pair<C, D>>, Pair<Pair<E, F>, Pair<G, H>> 

ps :하지 마세요. :)

+3

끝에 좋은 조언을 위해 +1 –

관련 문제