これは、Java でよく知られているイディオムです。たとえば、この SO ディスカッションを参照してください。したがって、基本的に、それを実装するクラスがそのクラスのオブジェクトと比較するメソッドを持つ必要があるインターフェイスを定義するには、次のようにします。
public interface IComparable<T extends IComparable<T>> {
public int compare(T item);
}
(注: 特定のユース ケースを解決するには、明らかに不必要に複雑な方法です。この投稿を参照してください。ただし、特定のアプリケーションは気にせずに、再帰構文を解釈する方法を調べています)。
要するに、これは再帰に明らかな終わりのない再帰的な定義であり、コンパイラ/型システムがこれをどのようにやってのけるのかわかりません。
また、言葉で表現しようとすると (「IComparable は、インスタンスが IComparable インターフェイスを実装するクラスのオブジェクトと比較できるクラスです」)、非論理的な循環定義が生成されます。これは、哲学/論理/数学では使用できませんが、明らかにコンパイラ設計で実行可能 (!)。
さらに、元の慣用句の構文が受け入れられる場合は、次のように言うことも許されるようです。
public interface IComparable<T extends IComparable<T extends IComparable<T>>> {
public int compare(T item);
}
...しかし、コンパイラは、明らかに1つのレベルのみを許可することに躊躇しますextend
。
この種の再帰的なジェネリック定義を理解するのを助けるために、誰かが光を当てることができますか?
アップデート
受け入れられた回答(BartoszKP)に基づいて、私が今理解していると思うのは次のとおりです。
「再帰的」定義は次のように読まれるべきではありません (「定義が依存する」関係を表す矢印)。
[ IComparable<T> ] -------> [ IComparable<T> ]
...これは非論理的(循環的)ですが、次のようになります。
[ IComparable<T> ] ----------> [ list of methods (parameterized by T) ]
\ ^
\ |
\-------> [ type bound on T ]-------/
...これは非論理的ではないため、コンパイラで実行できます。つまり、 の定義は、IComparable
それが定義するメソッドのリストと、それが定義するタイプの境界によって与えられT
、後者もメソッドのリストに依存します。したがって、再帰はありません。