私は次のことをしたいと思います:
public class ImmutableList<T> {
public <U super T> ImmutableList<U> add(U element) { ... }
}
つまり、 の不変リストが与えられたT
場合、 リストに anyU
を追加して の不変リストを生成でき、 のスーパータイプでなければならないU
という制約があります。例えばU
T
- サルのリストにサルを追加すると、新しいサルのリストが生成されます。
- サルのリストに人間を追加して、ヒト科の新しいリストを作成できます (おそらく、サルと人間の上限が最小です)。
- 人類のリストに岩を追加して、新しいリストを生成できます
Object
(岩と人類は他の共通の祖先を共有していないと仮定します)。
これは理論的には素晴らしいように思えますが、JLS では下限U
は合法ではありません。代わりに次のように書くこともできます:
public class ImmutableList<T> {
public ImmutableList<T> add(T element) { ... }
public static <U> ImmutableList<U> add(ImmutableList<? extends U> list, U element) { ... }
}
U
このようにして、コンパイラは、リストの要素型と追加したい要素型との間の最小上限を正しく推測します。これは合法です。それはまた吸う。比較:
// if 'U super T' were legal
list.add(monkey).add(human).add(rock);
// assuming 'import static ImmutableList.add'
add(add(add(list, monkey), human), rock);
私は関数型プログラミングの大ファンですが、Java コードを Lisp 方言のように見せたくありません。だから私は3つの質問があります:
なんてこと?
<U super T>
バウンドが合法でないのはなぜですか?この質問は実際に以前にここで尋ねられました ( 「Java 型パラメーターに下限を設定できないのはなぜですか?」 ) 。 、」私は実際には購入しません。JLS セクション 4.5.1は次のように述べています。上記の代替
static
メソッド シグネチャを考えると、コンパイラは明らかに必要な上限を推測できるため、引数が壊れているように見えます。そうではないと誰かが主張できますか?最も重要なこと:下限を持つメソッド署名の合法的な代替案を考えられる人はいますか?
list.add(monkey)
簡単に言えば、目標は、 Lisp ( ) ではなくJava ( ) のように見える呼び出しコードを持つことですadd(list, monkey)
。