java - Builder pattern with inheritance support generics issue -


i implemented pattern based on answer have following asbtract config:

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;     } } 

and have following concrete config:

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;     } } 

and how use it

dialogconfig config = new dialogconfig.dialogconfigbuilder()                 .setwidth(0)                 .setcalories(0)                 .setheight(0) //x line                 .build(); 

at x line - can't find symbol method setheight. mistake?

edit - have , extendeddialogconfig must extend dialogconfig , etc. mean there other subclasses.

you first change setcalories() to:

public builder<b> setcalories(int calories) {   this.calories = calories;   return this; } 

to rid of cast , warning. , @ closely. return builder. code doesn't know future subclasses. returns instance of base builder.

as consequence, when have chained call:

 .setheight(0) .build(); 

that return base builder. call build() - build abstract configuration. want assign more specific dialogconfig. error.

a (ugly) workaround:

dialogconfig.dialogconfigbuilder<?> builder = new dialogconfig.dialogconfigbuilder<>().setheight(0); builder.setcalories(0);  ...config = builder.build(); 

and solution - again reworking setcalories():

@suppresswarnings("unchecked") public <t extends b> t setcalories(int calories) {   this.calories = calories;   return (t) this; } 

fixes compile error; , allows chaining setcalories() call well. final exercise of getting rid of cast/suppress left exercise reader.

and record - "complete" solution, including adaptions rid of raw types , other warnings:

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);     } } 

Comments

Popular posts from this blog

python Tkinter Capturing keyboard events save as one single string -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

javascript - Z-index in d3.js -