1

Java で Generics を使用すると奇妙な問題が発生します。ジェネリックは私にとってまったく新しいものですが、基本は理解できたと思います。

このコードを見てください:

private void drawQuadtreeBoxes_helper(QuadTree<?> node) {
    if (node == null)
        return;

    Vector3 min = node.bbox.min;
    Vector3 max = node.bbox.max;
    // Draw the boxes (...)

    if (node.hasChildren()) {
        Array<QuadTree<?>> children = node.getChildren(); // ERROR HERE
        for (QuadTree<?> child : children) {
            drawQuadtreeBoxes_helper(child);
        }
    }
}

四分木構造内に格納されたオブジェクトのタイプはこのメソッドには関係ないため、このメソッドをすべての種類の四分木に適用できるように、メソッド シグネチャにワイルドカードを使用します。

メソッド getChildren() は、ノードの 4 つの子を返します。これは、Array と呼ばれるコレクション クラス内に格納されます (Arrayの実装)。getChildren() の戻り値の型は確かにArray<QuadTree<?>>(Eclipse でさえツールチップ内でそう言っている) と確信していますが、それでもこの行にエラーが表示され、次のように伝えられます。

cannot convert from Array<QuadTree<capture#6-of ?>> to Array<QuadTree<?>>

ここに楽しい部分があります。これを解決する方法について Eclipse に提案を求めると、これが提案の 1 つです。

Change type of 'children' to 'Array<QuadTree<?>>'

しかし、それはすでにこのタイプです!改善されました: この提案をクリックすると、Eclipse はこの行を次のように変更します。

Array<?> children = node.getChildren();

もちろん、これは以下のすべてのコードを破壊します。

ここで一体何が起こっているのですか?誰か教えてください。

4

3 に答える 3

4

問題は、メソッドが同じ であることを認識していないことですQuadTree<?>(同じ呼び出しで異なる?型を参照する可能性があります)。

解決策は、メソッドを「タイプ」することです。これにより、メソッド全体で同じQuadTree<?>タイプになるようにロックされます (したがって、?) 。

private <T extends QuadTree<?>> void drawQuadtreeBoxes_helper(T node) {
    if (node == null)
        return;

    Vector3 min = node.bbox.min;
    Vector3 max = node.bbox.max;
    // Draw the boxes (...)

    if (node.hasChildren()) {
        Array<T> children = node.getChildren(); // ERROR HERE
        for (T child : children) {
            drawQuadtreeBoxes_helper(child);
        }
    }
}


?「なんでも」という意味ですが、今は同じ「なんでも」です。

于 2012-07-06T18:52:07.963 に答える
1

ボヘミアンの答えに加えて、必要な同じ署名を引き続き使用できることを指摘したいと思います (この「T」型パラメーターを使用していることを誰も知る必要はありません。これは実装の詳細です。

これを行うには、元の型シグネチャを使用して、T を使用してジェネリック メソッドを呼び出すラッパー メソッドを作成します。呼び出しはキャプチャにより機能します。

private void drawQuadtreeBoxes_helper(QuadTree<?> node) {
    drawQuadtreeBoxes_helper_private(node);
}

private <T extends QuadTree<?>> void drawQuadtreeBoxes_helper_private(T node) {
    // code here ...
}

もちろん、この例のメソッドはプライベートであるため、わざわざこれをすべて行う必要はないかもしれません。しかし、それがパブリック API である場合は、T の不要な実装の詳細を抽象化するために、これを行うことをお勧めします。

于 2012-07-07T01:34:57.453 に答える
0

QuadTree 内の型引数を気にしない場合は、コードからどこでも削除するだけです:) 次のコードを試しただけで、コンパイラはそれを OK と見なします:

private void drawQuadtreeBoxes_helper(QuadTree node) {
    if (node == null)
        return;

    Vector3 min = node.bbox.min;
    Vector3 max = node.bbox.max;
    // Draw the boxes (...)

    if (node.hasChildren()) {
        Array<QuadTree> children = node.getChildren();
        for (QuadTree child : children) {
            drawQuadtreeBoxes_helper(child);
        }
    }
}
于 2012-07-06T19:06:06.573 に答える