12

私は次の意味を理解しようとしていますか?

public class Bar<T extends Bar<T>> extends Foo<T> {
    //Some code
}

このようなことを行うことの利点は何ですか(例:ユースケース?)。

4

5 に答える 5

7

これはかなり理論的な例ですが、次の場合に必要になる可能性があります。

public class Bar<T extends Bar<T>> extends Foo<T> {

    private final T value;

    public T getValue() { return value; }

    public void method(T param) {
        if (param.getValue().equals(someValue)) {
            doSomething();
        } else {
            doSomethingElse();
        }
    }
}

param.getValue()T が でない場合は呼び出すことができません。BarこれはT extends Bar<T>.

于 2012-09-04T17:00:38.560 に答える
4

java.lang.Enumこれは、クラスの定義方法と非常によく似ています。

public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
  private final String name;
  private final int ordinal;
  protected Enum(String name, int ordinal) {
    this.name = name; this.ordinal = ordinal;
  }
  public final String name() { return name; }
  public final int ordinal() { return ordinal; }
  public String toString() { return name; }
  public final int compareTo(E o) {
    return ordinal - o.ordinal;
  }
}

このように定義されたクラスは抽象でなければならず、直接インスタンス化できないため、パターンは通常の列挙型が展開される方法と同様の構造で役立ちます。

// corresponds to
// enum Season { WINTER, SPRING, SUMMER, FALL }
final class Season extends Enum<Season> {
  private Season(String name, int ordinal) { super(name,ordinal); }
  public static final Season WINTER = new Season("WINTER",0);
  public static final Season SPRING = new Season("SPRING",1);
  public static final Season SUMMER = new Season("SUMMER",2);
  public static final Season FALL   = new Season("FALL",3);
  private static final Season[] VALUES = { WINTER, SPRING, SUMMER, FALL };
  public static Season[] values() { return VALUES.clone(); }
  public static Season valueOf(String name) {
    for (Season e : VALUES) if (e.name().equals(name)) return e;
    throw new IllegalArgumentException();
  }

}

本「Java Generics and Collection」の例。

于 2012-09-04T20:30:02.903 に答える
3

Bar基本的に、拡張するものに「対処」するタイプの種類を制限していますBar<T>。この場合、 がBarそれ自体の拡張のみを処理していることを確認する必要があります。おそらく、 に対してプライベートなメソッドを呼び出しますBarBar簡単な例の 1 つは、このクラスを使用して一種のリンク リストを実装し、実行できる/実行する必要があることを実行しながらそれを反復処理することです。次のコードがあるとします。

public class Bar<T extends Bar<T>> extends Foo<T> {
    private T next;

    //Initialize next in constructor or somewhere else

    private void doSomethingOnlyBarCanDo(){
        //Do it...
    }

    public void iterate(){
        T t = next;
        while(t != null){
            t.doSomethingOnlyBarCanDo();
            t = t.next;
        }
    }
}

この種の構成では、インスタンスの「チェーン」を反復処理するのは非常に簡単Barです。各インスタンスには次への参照があるTためBar<T>です。

于 2012-09-04T17:06:41.393 に答える
2

典型的な使用例の 1 つは、Wrapper/Decorator パターンです。Barおそらくそれ自体Tを拡張するラップBarFooを扱う単なるパラメータ化されたクラスですT

public abstract class Foo<T> {
    public abstract void foo(T t);
}

public class Bar<T extends Bar<T>> extends Foo<T> {
    private T wrapped;
    public Bar(T w) {
         this.wrapped = w;
    }

    public abstract void foo(T t) {
        // do something 
    }
}
于 2012-09-04T17:03:18.567 に答える
0

私が言うことができる唯一のことは、<T extends Bar<T>>これを使用することです。これTは TypeBar<T>になりました。つまり、で利用可能なすべてのメソッドにアクセスできるということですT。.BarBarBar<T>T

では、用途は何ですか?

これは合成に使用できます。例えば

public class CustomList<T extends List<T>> {
    T t;

    T get(int index) {
        //Some custom code here
        return t.get(index);
    }
}

Bar クラス内の Bar クラスメソッドに常にアクセスできるため、 T が Bar 型であることを伝える本当の利点はないため、あなたの例は少し間違っています

于 2012-09-04T17:22:34.963 に答える