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
Post a Comment