自己参照ジェネリックをして、独自のインスタンスのバックを取得

it_is_not_you:

私は場所プロセッサ場所を処理します。場所を考えると、クライアントはその場所のためのプロセッサを要求することができます。私は、実装Location、次のとおりです。

public abstract class Location<SELF extends Location<SELF>> {
    ...

    public Processor<SELF> processor() {
        return new Processor(this);
    }
}

私が作成してからサブクラスを使用していますLocation決して、Location直接:

public class SecretLocation extends Location<SecretLocation> {
   ...
}

私は、型の安全性を必要とするプロセッサ上で、具体的なので、この秘密の場所クラスのインスタンスに属する唯一の参照は(ここでは省略)を設けることができる、それゆえの使用SELF及びサブクラス、および入力された提供Locationプロセッサにします。

今、私が実装したかったProcessor、次のとおりです。

public class Processor<L extends Location<L>> {
    private final L location;

    public Processor(L location) {
        this.location = location;
    }

    public L location() {
        return location;
    }

    ...
}

しかし、この実装で、new Processor(this)中にLocationは無効です。私はこれを解決するには、2つの方法を見つけましたが、私は最善である特定のではない午前:

  • やるnew Processor(this)代わりのnew Processor<>(this)中にLocation、その基本的にジェネリックを無効にします。

  • 受け入れLocation<L>の代わりLでコンストラクタとメンバ変数にProcessor結果はゲッターということであるlocationProcessor、今返さなければならないLocation<L>代わりにL、上記のように。欠点は、ということですprocessor.location()今戻らないだろう決してSecretLocation上のプロセッサを作成する際に、もはやSecretLocation、しかしLocation<SecretLocation>今私が得ることはできませんので、これは、ちょっとずさんであるSecretLocationプロセッサを介してバックを。

参考までに、これは私の第2の解決策は次のとおりです。

public class Processor<L extends Location<L>> {
    private final Location<L> location;

    public Processor(Location<L> location) {
        this.location = location;
    }

    public Location<L> location() {
        return location;
    }

    ...
}

よりよくするには何がありますか?

Radiodef:

この場合、最もストレートフォワードソリューションは、次のように考えられます:

public abstract class Location<SELF extends Location<SELF>> {
    ...

    public Processor<SELF> processor() {
        return new Processor<>( self() );
    }

    protected abstract SELF self();
}

public class SecretLocation extends Location<SecretLocation> {
    ...

    @Override
    protected SecretLocation self() { return this; }
}

問題は、バインドされ与えられた実際のタイプであることに型引数を制限していないということですthis例えば、以下のクラスがコンパイルだろう:

class BadLocation extends Location<SecretLocation> {}

他の解決策は、未チェックのキャストを使用することです:

return new Processor<>((SELF) this);

それも動作しますが、で示されるようにBadLocation、本当の制限はありませんthis、実際のオブジェクトですがSELF(ただし、ためabstractの方法ソリューション、サブクラスを返すために持っているという制限はありませんthis、それは正確さを保証することになるとどちらのソリューションが最適ですので、この方法では。)

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=190477&siteId=1