2010-12-17 18 views
1

は私がBuilderタイプまたはそのサブタイプのパラメータを汎用化することができ、親クラスBuilderを持っていますBuilderChildインスタンスのメソッドdoSmthを呼び出すことができ、BuilderChildを返します。総称化クラスと継承の問題

new BuilderChild().doSmth().doSmthElse(); 

しかし、BuilderChildを集計しようとすると、上記の行がコンパイルされなくなりました。

class BuilderChild<T> extends Builder<BuilderChild> { 

    BuilderChild doSmthElse() { 
     System.out.println("do smth else"); 
     return this; 
    } 
} 
... 
//Compile error, because doSmth() 
//returns Builder instead of BuilderChild. 
new BuilderChild().doSmth().doSmthElse(); 

doSmth()私はBuilderChildを汎用化した後Builderを返し始めた理由誰かが説明できますか?それを修正する方法はありますか?

答えて

5

問題は生タイプとしてBuilderChildを使用していることです。

これは型引数を持つことを意味しますが、型パラメータを指定せずに指定します。

これは、そのタイプのすべてのジェネリック情報が無視されることを意味します(それはa bit more complicated than thatですが、それは高レベルのビューです)。

あなたの代わりにこれを書いている場合:

new BuilderChild<Object>().doSmth().doSmthElse(); 

を、それがコンパイルされます。

また、doSmthElseBuilderChild<T> doSmthElse()と指定する必要があります。

ロータイプは下位互換性のためにのみサポートされているため、新しいコードでは使用しないでください。

0

私のような何かを提案します。クライアントコードは、おそらくビルダー非ジェネリック作ったほうが良いですが

abstract class Builder<T extends Builder> { 

    protected T getThis(); 

    @SuppressWarnings("unchecked") 
    T doSmth() { 
     System.out.println("do smth"); 
     return getThis(); 
    } 
} 

class BuilderChild extends Builder<BuilderChild> { 
    protected T getThis() { return this; } 
    [...]