4

ツリーの問題に取り組んでいるときにこれに遭遇しました:

class BTNode<T> {
    private final T value;
    private BTNode<T> parent;
    private BTNode<T> left;
    private BTNode<T> right;

    public BTNode(T aValue) { 
       value = aValue; 
       left = right = parent = null;
    }
  the obvious protected getters & setters
}

後で、Comparable である T のみを受け入れ、compareTo を定義し、そのプロパティを使用する新しいメソッドを追加するサブクラスが必要になりました。Java を快適に保つ以外に、ゲッターとセッターが行う必要がある新しいことは何もありません。

class CBTNode<T extends Comparable<T>> extends BTNode<T> 
                        implements Comparable<CBTNode<T>> {
    CBTNode(T aValue) { super(aValue); }
    T isBST() .... calls getLeft().isBST()  // for example
}

継承は一般的に簡単ですが、親クラスのフィールドはすべて型付き BTNode であるという事実により、実行時のクラス キャスト エラーが原因で、これが予想よりもはるかに難しくなっているようです。CBTNodes であるオブジェクトを作成できますが、それらのフィールドはまだ BTNodes であり、isBST() のような場所で問題を引き起こします。getLeft() は BTNode を返しますが、isBST は CBTNode に対してのみ定義されています。CBTNode にキャストしようとしたとき、Java はそれを好まなかった。

拡張/デリゲート/他の CBTNode の推奨される方法は何ですか? これは大きなクラスではありません。2 つのノード間のリンクを切断し、CBTNode を BTNode のコピーとして定義することもできますが、CBTNode フィールドを使用することもできますが、これはかなり醜いようです。私は新しい機能を委譲することを考えましたが、BTNode から CBTNode にキャストするという問題が残っていました。これは Java のオブジェクトです。私は、私の鼻を噛むのを待っている、明白でエレガントなアプローチを見過ごしていることを願っています.

4

1 に答える 1

4

Jim が言ったように、getter (getLeft()、getRight()、getParent()) をオーバーライドして、型を絞り込むことができます。

この領域は特に簡単ではありません。上記が本当にきちんと機能する唯一の解決策です。これと非常によく似た状況に触れたコードがかなりあります。

public class CBTNode<T extends Comparable<T>> 
        extends BTNode<T>
        implements Comparable<CBTNode<T>> 
        {

    @Override
    protected CBTNode<T> getParent() {return (CBTNode<T>) parent;}

    @Override
    protected CBTNode<T> getLeft() {return (CBTNode<T>) left;}

    @Override
    protected CBTNode<T> getRight() {return (CBTNode<T>) right;}

クラスをそれ自体に対してジェネリック化するという別の代替案は、実際には機能しません。

これを処理するためにジェネリックを使用しようとすると (たとえば、ノード タイプ自体をジェネリック パラメーターとして配置すると) class BTNode<T, NodeT extends BTNode>、コードがかなり複雑になりますが、実際には役に立たないことがわかります。(すべての型パラメーターが完全に指定されていない限り、推論は機能せず、キャストが面倒になり、実際には機能していないように見えます。)

問題の 1 つは、境界が異なるジェネリック間のキャストが有効でないことです。ジェネリック ルールは、コンパイラが有効であることを確認したり、消去のために実行時にテストしたりできないため、より厳密です。ここでの厄介な回避策は、2 つのキャストを使用することです。最初に生の型にキャストし、次に目的のパラメーター化された型にキャストします。

于 2013-09-25T00:10:12.123 に答える