web-dev-qa-db-ja.com

型変数がそれ自体の境界に現れるためのジェネリックによる境界メカニズム

From Programming Languages:Principles and Paradigms By Maurizio Gabbrielli、Simone Martini

型変数のバインドされたメカニズムはかなり洗練されており、柔軟性があります。特に、型変数はそれ自体の境界に現れる可能性があります。このケースの1つの例に限定し、より深い議論のために読者に参考文献を紹介します。

クラスがComparableインターフェースを実装している場合、クラスの要素は同等です。ジェネリック型の要素のリストを引数として指定し、このリストの最大要素を返すメソッドを定義したいと思います。このmaxメソッドに与えることができる署名は何ですか?最初の試みは次のとおりです。

_public static <T extends Comparable<T>>
T max(List<T> list)
_

これは、リストの要素が同じタイプの要素と比較可能でなければならないという事実を表しています。ここで、maxを使用しようとします。オブジェクトを比較できるタイプFooがあります。

_class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;
_

ここで、max(cf)を呼び出します。cfの各要素(Fooであるため)は、すべてのオブジェクト、特にすべてのFooと同等です。ただし、Fooは_Comparable<Foo>_を実装していないため、コンパイラはエラーを通知します。実際には、Fooがそれ自体のスーパータイプの1つと同等であるだけで十分です。

_public static <T extends Comparable<? super T>>
T max(List<T> list)
_

これで、以前と同じ条件下で、Fooは_Comparable<Object>_を実装するため、Max(cf)は正しいです。

  1. _? super T_はTのスーパータイプを意味すると思います。

    ObjectTのスーパータイプなので、次のmaxの署名は機能しますか?

    _ public static <T extends Comparable<Object>>
     T max(List<T> list)
    _

    はいの場合、引用の最後のものの代わりにそれを使用してみませんか?

  2. これは、Comparableインターフェースを含むexampleです。引用符のメソッドを使用して解決できる一般的な問題とは何ですか?
4
Tim

私たちが持っていた場合:

public static <T extends Comparable<Object>>
T max(List<T> list)

それは一緒に働いていただろう

class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;

しかし、

class Bar implements Comparable<Bar>{...}
List<Bar> cf = ....;

彼らの最初のmax署名は、TTと比較できることを要求します-したがって、ListsはFooと比較できるため、FoosのObjectでは機能しません。 max署名では、TObjectと比較できる必要があります。したがって、Listは別のBarとしか比較できないため、BarsのBarでは機能しません。

List<Foo>List<Bar>の両方で機能するには、2番目のmaxバージョンが必要です。 「そのタイプの他のオブジェクトと比較できるもののリストを教えてください。ただし、他のタイプも受け入れる、より広い比較方法がある場合は、それが受け入れられる限り、問題ありません。独自のタイプです。 "。

したがって、Baz implements Comparable<Foo>のリストは問題外です。これは、Bazをそれ自体(Baz is not a subclass ofFoo`)と比較できないためです。

基本的に、このメソッドによって解決される一般的な問題は、ジェネリックパラメーターのサブクラス/スーパークラスで動作する可能性があることです。これは、ジェネリックパラメーターとの間でのみアップキャストされるためです。 ? super T/? extends Tを使用してこれを署名にエンコードし、ジェネリックをさまざまなタイプで使用できるようにします。

3
Idan Arye