2017-08-15 7 views
1

I実装に基づいてパターンこのanswer I次asbtract設定があります。ビルダーパターン

public abstract class AbstractConfig { 

    public static abstract class Builder<B extends Builder<B>> { 

     private int calories = 0; 

     public Builder() { 

     } 

     public B setCalories(int calories) { 
      this.calories = calories; 
      return (B) this; 
     } 

     public abstract AbstractConfig build(); 
    } 

    private int calories = 0; 

    protected AbstractConfig(final Builder builder) { 
     calories = builder.calories; 
    } 
} 

そして、私は、以下の具体的な設定があります。

public class DialogConfig extends AbstractConfig { 

    public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> { 

     private double width; 

     private double height; 

     public DialogConfigBuilder() { 
      //does nothing. 
     } 

     public B setWidth(final double value) { 
      width = value; 
      return (B) this; 
     } 

     public B setHeight(final double value) { 
      height = value; 
      return (B) this; 
     } 
     public DialogConfig build() { 
      return new DialogConfig(this); 
     } 
    } 

    private final double width; 

    private final double height; 

    protected DialogConfig(final DialogConfigBuilder builder) { 
     super(builder); 
     width = builder.width; 
     height = builder.height; 
    } 

    public double getWidth() { 
     return width; 
    } 

    public double getHeight() { 
     return height; 
    } 
} 

そして、これがあるとどのように使用するのですか

DialogConfig config = new DialogConfig.DialogConfigBuilder() 
       .setWidth(0) 
       .setCalories(0) 
       .setHeight(0) //X LINE 
       .build(); 

X l私は得る - シンボルメソッドsetHeightを見つけることができません。私の間違いは何ですか?

EDIT - 私はDialogConfigなどを拡張する必要があるExtendedDialogConfigを持っています。他のサブクラスもあるはずです。

+2

あなたは 'B'が'ビルダー 'に解決することを意味する生の型を使用しています。クラス宣言を 'class DialogConfigBuilder extends Builder 'に変更してください。 – shmosel

+0

このソリューションは[生の種類を使用する](https://stackoverflow.com/questions/17164375/subclassing-a-java-builder-class/17165079#comment59589591_17165079)としてコピーすることには注意が必要です。 – shmosel

+0

@shmoselあなたのコメントよりも。しかし、 'DialogConfigBuilder extends Builder 'クラスに変更すると、SuperDialogConfigでDialogConfigを拡張できますか?私はあなたのアドバイスに従うと、setCalories()はDialogConfigを返しますが、SuperDialogConfigは返しません。 –

答えて

1

私は私のミスを発見しました。これは、私はこれは私が第二の場合には<>にDialogConfigBuilder

DialogConfig config = new DialogConfig.DialogConfigBuilder<>() 
       .setWidth(0) 
       .setCalories(0) 
       .setHeight(0) //X LINE 
       .build(); 

ご注意を使用する方法であるDialogConfigBuilder

DialogConfig config = new DialogConfig.DialogConfigBuilder() 
       .setWidth(0) 
       .setCalories(0) 
       .setHeight(0) //X LINE 
       .build(); 

使用する方法です。

+0

あなたは自分の答えを受け入れるべきです。そして、おそらく太い一番最初の行を置くかもしれません "私の間違いは**生の**型を使用することでした、そして、今私は誰もが**生の**型*"を使わないと言う理由を理解しています;-) – GhostCat

2

あなたは最初にsetCalories()を変更します:そのキャストとの警告を取り除くために

public Builder<B> setCalories(int calories) { 
    this.calories = calories; 
    return this; 
} 

。そして今これをよく見る。 ビルダーを返します。このコードは将来のサブクラスについては知らない。そのベースビルダーのインスタンスのみを返します。結果として

、あなたが連鎖呼び出していることがあります。

.setHeight(0) .build(); 

そのベースビルダーを返すだろうと。 build()を呼び出すには、抽象の設定が必要です。しかし、それをより具体的なDialogConfigに割り当てる必要があります。したがって、エラー。

A(醜い)回避策:

DialogConfig.DialogConfigBuilder<?> builder = new DialogConfig.DialogConfigBuilder<>().setHeight(0); 
builder.setCalories(0); 

...config = builder.build(); 

そして溶液 - 再度setCalories()を再加工することにより:

@SuppressWarnings("unchecked") 
public <T extends B> T setCalories(int calories) { 
    this.calories = calories; 
    return (T) this; 
} 

修正、コンパイルエラー。また、setCalories()コールも連鎖させることができます。キャスト/抑制を取り除く最終的な行使は、読者に運動として残されます。

とレコードのための - 生の種類やその他の警告を取り除くために、すべてのadaptionsを含む「完全な」解決策、:

abstract class AbstractConfig { 
    public static abstract class Builder<B extends Builder<B>> { 
     private int calories = 0; 

     @SuppressWarnings("unchecked") 
     public <T extends B> T setCalories(int calories) { 
      this.calories = calories; 
      return (T) this; 
     } 

     public abstract AbstractConfig build(); 
    } 

    private int calories = 0; 
    public int getCalories() { return calories; } 

    protected <B extends Builder<B>> AbstractConfig(final Builder<B> builder) { 
     calories = builder.calories; 
    } 
} 

final class DialogConfig extends AbstractConfig { 
    public static class DialogConfigBuilder<B extends DialogConfigBuilder<B>> extends Builder<B> { 

     private double width;  
     private double height; 

     public DialogConfigBuilder<B> setWidth(final double value) { 
      width = value; 
      return this; 
     } 

     public DialogConfigBuilder<B> setHeight(final double value) { 
      height = value; 
      return this; 
     } 

     public DialogConfig build() { 
      return new DialogConfig(this); 
     } 
    } 

    private final double width; 
    private final double height; 

    protected <B extends DialogConfigBuilder<B>> DialogConfig(final DialogConfigBuilder<B> builder) { 
     super(builder); 
     width = builder.width; 
     height = builder.height; 
    } 

    public double getWidth() { return width; } 
    public double getHeight() { return height; } 
} 

public class Builders { 
    public static void main(String[] args) { 
     DialogConfig config = new DialogConfig.DialogConfigBuilder<>().setHeight(0).setCalories(0).build(); 
     System.out.println(config); 
    } 
} 
+0

あなたのソリューションでは、DialogConfigを最終的にして、DialogConfigBuilder DialogConfigBuilderを返します。これは私が必要とするものではありません。 DialogConfigを他のサブクラスで拡張する必要があると書いてあり、各サブクラスはビルダー・パターンを実装する必要があります。 –

+0

@Pavel_Kこれは** my **コードではありません。私はあなたの意見からコピーしました。また、これは与えられたタスクの入力を「完了」しようとすることに過ぎません。そのクラスから 'final'を削除すると、何も変わりません。そして、変更された戻り値の型はキャストと警告を**取り除くことについてです! – GhostCat

+0

私はしばらく時間が必要です –

関連する問題