2

まず、これにはユースケースはないと言いたいです。私がやろうとしている唯一のことは、これが可能かどうかを調べることです.

私がやろうとしているのは、基本インターフェースのメソッドの戻り署名を子インターフェースの戻り署名に「ブランド変更」することです。

目標: メソッドを 1 回宣言して実装しますが、サブインターフェイスに一致するように戻り値の型を変更します。場合によってはこれを達成する方法を見つけましたが、特定の状況では機能しません。

ベース インターフェイス B があり、メソッド B doWork() があるとします。また、doWork() を実装する B の実装もあります。doWork() の性質上、この実装だけが存在するはずです。

さて、これは Generics で非常に簡単に行うことができます。上記の例の場合:

interface B<T extends B> {
    T doWork();
}

class BImpl<T extends B> implements B<T> {
    @Override
    public T doWork() { return something; }
}

子インターフェイス/impl は次のようになります。

interface C extends B<C> {
    void somethingCSpecific();
}

class CImpl extends BImpl<C> implements C {
    @Override
    public void somethingCSpecific() {   }
}

CImpl を構築する人は誰でも、doWork() が C を返すことに気付くでしょう。

C obj = new CImpl().doWork()  // The money shot.  No casting needed.

B が次のようになっていると想像してください。

public interface B<T extends B> {
    T thisOrThat(T that);
    boolean something();
}

そして、BImplでこれを行いたい:

class BImpl<T extends B> implements B<T> {
    @Override
    public T thisOrThat(T that) {
        if (that.something())
            return that;
        return this;  //  Error!!  _this_ might be a different T than _that_.
    }
    @Override
    public boolean something()  { return whatever; }
}

エラーが発生した場所に注意してください。

明らかに、これは危険で疑わしいキャストなしでは機能しません。しかし、上記の thisOrThat メソッドでの this の実装が that の実装と同じであることがわかっていればすべて問題ありません。

それで、私の質問に。その型をアプリオリに知らなくても、これそれを同じ型に制限する方法はありますか?

それとも、これを行う別の方法がありますが、同じ結果が得られますか? つまり、thisOrThat() を 1 回だけ宣言して実装するだけで、戻り値の型をサブインターフェイスに適応させることができますか?

ありがとう。

4

2 に答える 2

3

クラスを抽象化し、抽象基本クラスを拡張する特定のクラスによって実装されるビューBImplメソッドをクラスに追加します。

public abstract class BImpl<T extends B<T>> implements B<T> {
   @Override
   public T thisOrThat(T that) {
       if (that.something())
           return that;
       return this.asT();
   }


    @Override
    public boolean something() {
        // TODO Auto-generated method stub
        return false;
    }

    protected abstract T asT();
}

その後もすべてのクラスを実装する必要がありますT asT()が、これは簡単で、警告なしでコンパイルされます。

public class C extends BImpl<C> implements B<C> {
    @Override
    protected C asT() {
        return this;
    }
}
于 2012-04-18T22:49:58.310 に答える
2

あなたの問題を正しく理解している場合、それを解決する方法は、一種の自己参照ジェネリックを使用することですB<T extends B<T>>

あなたが望むのは だと思いますclass BImpl implements B<BImpl>。その場合、すべての型が正常にチェックされます。

于 2012-04-18T21:46:02.350 に答える