2011-01-05 6 views
1

各レベルに固有のオブジェクトタイプがあるJavaでツリークラスを作成する必要があります。下に書かれている方法は、ジェネリックを利用せず、重複したコードをたくさん作成します。ジェネリックスでこれを書く方法はありますか?各レベルに一意のオブジェクトタイプがある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型は、特定のインターフェイスを実装して作ることができます。

EDIT:ノード・カウントの取得のための再帰的な方法で更新され、実装

1

これは、「ノード」から継承するすべてのための理想的な場所ですが、でもそれは不要です。\

あなたはおそらくしたいことはあなたの別のクラスへの参照を含む単一の一般的な「ノード」オブジェクトであります(継承の前に構成を使用する)。

その時点で、それぞれの異なるクラスは、おそらくそれらに実行できる何かを持っています(そうでなければ、それらはすべて同じデータ構造にあります)。ノードクラスは、このインタフェースに委譲できます。または、他のクラスがこのインタフェースでクラスを抽出し、それに基づいて動作することができます。

これはノードにも何かを強制しようとするよりも良いでしょう - 簡単なことをしてください。

--edit--私は本当にあなたのシナリオについては何も投稿していなかったので、あなたに関連する例を追加することはできません。

しかし、あなたはこれらの異なるクラスA、B * Cを持っているとしましょう。オブジェクトの子であることを除けば、まずすべてATに関連していますか?彼らがすべてインターフェイス「Iface」を実装しているとしましょう。 (ない場合は、単に「オブジェクト」とのifaceを置き換えることができますが、これは本当に悪いデザインを意味します。)

をとにかく、あなたの「ノード」オブジェクトは今ちょうど1 object--

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

これはありますあなたのツリーを作成するのに十分です。物事をスムーズにするためにできることの1つは、「Node Implements Iface」を持って、そのオブジェクトにすべての呼び出しを委譲します。 IFACEが食べる(食品foodtype)メソッドが含まれている場合たとえば、あなたのノードがIFACEを実装し、方法かもしれない:それはそれが含まクラスだったかのよう

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

をこれは、「ノード」クラス行為になるだろう。

ところで、この時点では、myObjectを "private final"にして、コンストラクタでnullでないことを確認するのが良いでしょう。そうすれば、あなたはそれが設定されており、委任されたメンバーのどれもがヌルチェックをしなければならないことをいつも知るでしょう。

+0

例を挙げて詳しく説明できますか? – user479576

0

この場合、ジェネリックスがあなたに多くの助けになるとは思わない。ツリーの各レベルに異なるクラスを持つ代わりに。子を持ち、各レベルに異なるクラスを格納するノードクラスはどうでしょうか。それは重複の多くを排除するのに役立ちます。

+0

ご返信ありがとうございます。それで、あなたはどのようにして1つのクラスの階層を表現しようとしていますか? – user479576

+0

私が言及したように、単一のNodeクラスを使用するだけです。 NodeAクラスやTreeクラスに似ていますが、String以外のオブジェクト型を格納します。 – jzd

0

私は、Javaにかなり新しいですので、これは、私は認識していないよな問題があるかもしれませんが、少なくとも、単純なレベルで動作するようです。

メインのNodeクラスを定義します。これはツリーのルートになります。

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のコードは、B'sがC'sの明白な置き換えを除いて同じです。

希望がありますように/あなたが望む答えの種類です!

+0

唯一の問題は、もう1つのノードタイプ(NodeX、NodeZなど)を追加するたびに、基本クラス(NodeA)を更新する必要があることです。 –

+0

良い点。 switch文を使用する代わりにadd(addchildにも名前を変更する必要があります)を各サブクラスでオーバーライドすることをお勧めします。そうすれば_depthも不要になります。 –

2

あなたが必要なのはです。木の例:

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 –

関連する問題