0

(一般的に入力された)ワイルドカードを使用できない(そう思われる)場合、なぜこのような有界ワイルドカードを使用できるのか理解するのに苦労しています。

クラスにワイルドカードフィールドがある場合、実装されたインターフェイスのジェネリックパラメーターを持つメソッドを使用できません(null引数として指定しない限り)。

class SomeClass {}

class DerivedClass extends SomeClass {}

interface IInterf<T extends SomeClass> {
    T returnsT();
    void paramT(T parm);
    T paramAndReturnT(T parm);
    int nonGenericMethod(int x);
}

class Impl {
    protected IInterf<?> field; //this is bound to <extends SomeClass>
                                //- it's implied by the definition 
                                //  of IInterf which is bound
                                // but what's the point?

    public Impl(IInterf<? extends SomeClass> var){
        field = var;
    }
    public void doSmth(){

        SomeClass sc = field.returnsT();  //works

        field.paramT(new SomeClass());
          //error: method paramT in interface IInterf<T> cannot be applied to given types;
          //required: CAP#1
          //found: SomeClass
          //reason: actual argument SomeClass cannot be converted to CAP#1 by method invocation conversion
          //where T is a type-variable:
          //  T extends SomeClass declared in interface IInterf
          //where CAP#1 is a fresh type-variable:
          //  CAP#1 extends SomeClass from capture of ? 

         field.paramT(null); //works

        SomeClass sc2 = field.paramAndReturnT(new DerivedClass());
          //error: method paramAndReturnT in interface IInterf<T> cannot be applied to given types;
          // SomeClass sc2 = field.paramAndReturnT(new DerivedClass());           //required: CAP#1
          //found: DerivedClass
          //reason: actual argument DerivedClass cannot be converted to CAP#1 by method invocation conversion
          //where T is a type-variable:
          //  T extends SomeClass declared in interface IInterf
          //where CAP#1 is a fresh type-variable:
          //  CAP#1 extends SomeClass from capture of ?            
          //
        int x = field.nonGenericMethod(5);  //obviously works.
    }
}

FWIW、C#コンパイラに同様のものを受け入れるように説得することはできませんでした。

私は何かが足りないのですか?

4

3 に答える 3

1

fieldとして宣言すると

protected IInterf<?> field;

は、?を拡張する未知のクラスを表しますSomeClass。ワイルドカードとしてではなく、派生するSomeClassが匿名の特定のクラスと考えてください。

今電話しようとしたら

field.paramT(new SomeClass());

インスタンスがの略語、つまり を拡張する匿名クラスとSomeClass互換性がないため、これは失敗します。?SomeClass

使用には問題ありませんnull。これはどのクラスにも対応しています。

まったく同じことが起こります

SomeClass sc2 = field.paramAndReturnT(new DerivedClass());
于 2013-01-12T16:03:35.033 に答える
0

そうです、これらの方法は使用できません。多くの場合、これらのメソッドは必要ありません (たとえば、<? extends T>コレクションに何かを追加し<T>ます。それ以上の情報が必要ない場合は、それらを使用するのが理にかなっています。これらのメソッドを呼び出す必要がある場合は、ワイルドカードを使用できません。代わりに、次のことができます<T extends SomeClass>

于 2013-01-12T16:03:39.320 に答える
0

必要のないジェネリック/ワイルドカードを使用しようとしています。代わりに、次のいずれかが機能します。

1) 任意のクラスを受け入れるようにインターフェイスを定義し、インターフェイスを使用するときに型を制限します。

interface IInterf<T> {}
protected IInterf<SomeClass> field;

2) を拡張するクラスを受け入れるようにインターフェースを定義し、SomeClass追加の型情報を指定せずにインターフェースを使用します。

interface IInterf<T extends SomeClass> {}
protected IInterf field;

ワイルドカードが機能しない理由については、 の未知のサブタイプを? extends SomeClass意味します。型がわからないので、それが(または2 番目のメソッド呼び出しで) のスーパータイプであるかどうかもわかりません。そのようなスーパータイプである場合とそうでない場合があるため、渡すのは安全ではありません(または)。( Java ワイルドカードのドキュメントから)SomeClassSomeClassDerivedClassSomeClassDerivedClass

于 2013-01-12T16:15:24.997 に答える