3

私は現在、次のタイプで作業しています。

// A Field whose values are of type V.
interface Field<V> {
    public V getValue();
}

// A Field whose values are of type V and that has a LabelProvider for those values.
interface LabelField<V> extends Field<V> {
    public LabelProvider<V> getLabelProvider();
}

これらは図書館からのものであり、私はそれらを変更することはできません。これはおそらく関係ありませんが、LabelProviderは基本的に、タイプVの値を文字列に変換するクラスです。

次に、次のようなインターフェイスを提供するクラスを作成します。

// A Wrapper class for Fields of values V
interface IWrapper<V, F extends Field<V>> {
    public F getField();
    public V getValue();
    public String getLabel();
}

クラスはフィールドをラップし、そのユーザーがフィールドから値を取得できるようにしますが、ラベルの取得などの他の機能も提供します。これが私が持っているものです:

public class Wrapper<V, F extends Field<V>> {

    private F field;
    private LabelProvider<V> labelProvider; // Converts from V to String

    // Since we have no guarantee that F has a LabelProvider, one is explicitely supplied.
    public Wrapper(F field, LabelProvider<V> labelProvider) {
        this.field = field;
        this.labelProvider = labelProvider;
    }

    private String getLabel() {
        return labelProvider.getLabel(field.getValue());
    }

    public F getField() {
        return field;
    }

    public V getValue() {
        return field.getValue();
    }
}
  1. これらの2つのジェネリック型が必要かどうかはわかりませんが、この時点までは問題ありません。理想的には、Wrapper>を使用して、FとVの両方にアクセスできるようにすることをお勧めします。これは不可能であり、上記がこれを行う正しい方法だと思いますか?

  2. これが本当の問題です。

LabelFieldタイプのより具体的なコンストラクターが必要です。これは次のようになります。

public Wrapper(LabelField<V> labelField) {
    // Use the field's own label provider
    this(labelField, labelField.getLabelProvider());
}

この場合、labelproviderをフィールドから抽出できます。しかし、コンパイラはこれを気に入らず、次のエラーが発生します。

The constructor Wrapper<V,F>(LabelField<V>, LabelProvider<V>) is undefined

同じ型を使用するこのメソッドはコンパイルしますが:

public static <X> void test(LabelField<X> lf) {
    LabelProvider<X> lp = lf.getLabelProvider();
    new Wrapper<X, LabelField<X>>(lf, lp);
}

2番目のコンストラクターがコンパイルされないのはなぜですか?

これがSSCEです:http://pastebin.com/UqLJhJA7

4

2 に答える 2

1

Fを拡張する任意のタイプにすることができField<V>、そのタイプは必ずしも。ではありませんLabelField

たとえば、FooFieldを実装Field<Object>して使用するクラスを作成した場合Wrapper<Object, FooField>LabelFieldコンストラクターは一致しません。

この方法でラッパーを単純化できます(これも最初のポイントに答えます):

public class Wrapper<V> {

    private Field<V> field;

    private LabelProvider<V> labelProvider; // Converts from V to String

    // Since we have no guarantee that F has a LabelProvider, one is explicitely
    // supplied.
    public Wrapper(Field<V> field, LabelProvider<V> labelProvider) {
        this.field = field;
        this.labelProvider = labelProvider;
    }

    public Wrapper(LabelField<V> labelField) {
        // Use the field's own label provider
        this(labelField, labelField.getLabelProvider());
    }

    private String getLabel() {
        return this.labelProvider.getLabel(this.field.getValue());
    }

    public Field<V> getField() {
        return this.field;
    }

    public V getValue() {
        return this.field.getValue();
    }
}

This uses "regular" polymorphism instead of generics for field.

于 2012-12-18T13:44:59.920 に答える
0

You mixed generics and inheritance.

You should parametrize only with V:

public class Wrapper<V>

and write below

Field<V>

in all places you would write

F
于 2012-12-18T14:09:42.873 に答える