これは、Java で、実装クラス自体を参照するメソッドとのインターフェースを持つ唯一の方法です。したがって、たとえば、バイナリ ツリー ノード インターフェイスを次のように記述できます。
interface TreeNode<N extends TreeNode<N>> {
N getLeftChild();
N getRightChild();
void setLeftChild(N node);
void setRightChild(N node);
}
そして、次のようなクラスがあります
class TreeNodeWithInt extends TreeNode<TreeNodeWithInt> {
int value;
TreeNodeWithInt leftChild;
TreeNodeWithInt rightChild;
public TreeNodeWithInt getLeftChild() { return leftChild; }
public void setLeftChild(TreeNodeWithInt newLeft) { leftChild = newLeft; }
...
}
型パラメーターがなければ、次のN
ような安全でないコードを書く必要があります。
class TreeNodeWithInt extends TreeNode {
int value;
TreeNodeWithInt leftChild;
TreeNodeWithInt rightChild;
public void setLeftChild(TreeNode node) {
// note the dangerous cast!
leftChild = (TreeNodeWithInt) node;
}
}
ここでの重要な問題は、メソッドの入力と戻りの型を記述するときに、インターフェイスを実装しているクラスの型をインターフェイスが参照できないことです。代わりに、「self」ジェネリック型パラメーターを含めます。これは、ジェネリックを多用するコードで比較的一般的なイディオムです。
あなたが正しく識別したように、オブジェクトを同じタイプの他のオブジェクトとしか比較できないためComparable
、具体的に頻繁に使用されます。実際、はwhereを取るように指定されています。これは、少なくともtype の他の値に匹敵することを意味しますが、おそらく他の値にも匹敵します。Collections.sort
List<T>
T extends Comparable<? super T>
T
T
(最後に、ご想像のとおり、これはこの動作を実現する唯一の方法であるため、「良い」または「悪い」プラクティスではありません。とはいえ、この手法の目標は、警告なしでコンパイルされるが終了する可能性のあるメソッドを作成しないようにすることです。それClassCastException
自体が良い練習です。)