5

ノードとエッジ G(N,E) のグラフでさまざまな分析アルゴリズムを実行するアプリケーションがあります。ノードとエッジの属性はアプリケーションによって異なり、グラフのタイプと属性の性質に基づいて継承階層を形成します。たとえば、ノード階層のルートは、最も一般的な無向巡回グラフ (NcgNode) を表すことができます。NcgNode のサブクラスは有向巡回グラフ (DcgNode) を表し、その後に DagNode などが続きます。DAG に適用できるアルゴリズムは NCG のアルゴリズムとは異なりますが、その逆ではありません。ツリーのルートの重要な動作は、グラフの隣接ノードを追加および取得することです。問題は、「チェックされていない」例外を作成せずにこれを行う方法です。

コードの簡潔なバージョンは次のようになります。

import java.util.ArrayList;
import java.util.List;

public class NcgNode {
    private List<NcgNode> nodeList_ = null;
    private List<? extends NcgNode> nodeListSrc_ = null;
    private List<? super NcgNode> nodeListSink_ = null;

    public <N extends NcgNode> void addNode(N node) {
        if (nodeList_ == null) {
            nodeList_ = new ArrayList<NcgNode>();
            nodeListSrc_ = nodeList_;
            nodeListSink_ = nodeList_;
        }
        nodeListSink_.add(node);
    }

    @SuppressWarnings("unchecked")
    // Any way to avoid this?
    public <N extends NcgNode> N getNode(int n) {
        if ((nodeList_ == null) || (n >= nodeList_.size()))
            return null;
        // causes unchecked warning:
        return (N) nodeListSrc_.get(n);
    }
}

class DcgNode extends NcgNode {
    // enables DCG algorithms, etc
}

class DagNode extends DcgNode {
    // enables DAG algorithms, etc.
}

これを設計するより良い方法はありますか?

4

4 に答える 4

1

リストのタイプをNcgNodeにするだけです。

private List<NcgNode> nodeListSrc_ = null;

NcgNodeのサブクラスをこれらのリストに入れることはできます。

于 2012-12-19T02:22:29.073 に答える
1

次のようにする必要があります。メソッドを抽象クラス ( NcgNode) で定義し、子の型でパラメーター化します。したがって、addNode簡単getNodeに書くことができます。次に、特定の実装(私が使用したものDcgNodeDagNode、これがあなたが望むものかどうかはわかりません)が、それ自体でパラメータ化された this のサブクラスになります。これにより、ノードの子がノードと同じタイプであることを必要とする後で (以下を参照) アルゴリズムを持つことができます。

public abstract class NcgNode<N> {
    private List<N> nodeList_ = null;

    public void addNode(N node) {
        if (nodeList_ == null) {
            nodeList_ = new ArrayList<N>();
        }
        nodeList_.add(node);
    }

    // Any way to avoid this?
    public N getNode(int n) {
        if ((nodeList_ == null) || (n >= nodeList_.size()))
            return null;
        return nodeList_.get(n);
    }
}

class DcgNode extends NcgNode<DcgNode> {
    // enables DCG algorithms, etc
}

class DagNode extends NcgNode<DagNode> {
    // enables DAG algorithms, etc.
}

//...
static <N extends NcgNode<N>> void someAlgorithm(N node) { }

DagNodeのサブクラスであるという考えはDcgNode安全ではありません。DagNode「is-a」の場合、それは任意のものをその子としてDcgNode入れることができることを意味するためです。これはあなたが望むものではありません。DcgNode

于 2012-12-19T10:31:15.940 に答える
0

以下のようにメソッドを変更します。

public NcgNode getNode(int n) {
  if ((nodeList_ == null) || (n >= nodeList_.size())) {
  return null;
}

return (NcgNode) nodeListSrc_.get(n);
} 
于 2012-12-19T01:59:45.680 に答える
0

「自己境界型」を確認してください。(編集:ここで反対票を理解しているかどうかわかりません)

次のように、ルート クラスは抽象であり、実際のノード タイプNはクラスの型パラメータである必要があります。

public abstract class AbstractNode< N extends AbstractNode< N > > {
    private List< N > nodeList_ = null;

    public synchronized void addNode( N node ) {
        if ( nodeList_ == null )
            nodeList_ = new ArrayList< N >();
        nodeList_.add(node);
    }

    public N getNode( int n ) {
        if ( nodeList_ == null || n >= nodeList_.size() )
            throw new NoSuchElementException();
        return nodeList_.get( n );
    }
}

具象サブクラスは、独自の型を N として提供できます。継承階層が深い場合は、別の抽象クラスで「My Type」を維持します。

class NcgNode extends AbstractNode< NcgNode > {
}

abstract class AbstractDcgNode< N extends AbstractDcgNode< N > > extends AbstractNode< N > {
    // enables DCG algorithms, etc
}

class DcgNode extends AbstractDcgNode< DcgNode > {
}

class DagNode extends AbstractDcgNode< DagNode > {
    // enables DAG algorithms, etc
}
于 2012-12-19T02:12:32.293 に答える