How to write a reusable builder class with a flowing interface - java

I have a couple of classes 'X' and 'Y' that extend a common abstract class 'Base'. Almost all of the configuration is in Base. As the configuration can be complex and needs to be flexible I would like to write Builder classes for X and Y that have flowing interfaces.
It occurs to me that most of the setter methods in the builders will be identical - after all the common code is in the common base class. I should therefore probably write an abstract Builder for 'base'. This would look like:
abstract class Base {
abstract static class Builder {
private int a;
Builder setA(int a) {
this.a = a;
return this;
}
}
}
public class X extends Base {
static class Builder extends Base.Builder {
X build() {
// Do some stuff with the configuration
return new X();
}
}
}
Class 'Y' would look a lot like 'X'
the client could should read
X x = new X.Builder().setA(1234).build();
But this won't work because setA() returns a Base.Builder, which doesn't implement build
I don't particularly want to overload each method in the derived builders to return the correct type. That's a lot of boilerplate code and a maintenance headache.
Is there some trick I can use with Generics to tell the abstract builder what it's derived class is?

EDIT: Improved Version
The original answer (see below) did not support for the derived builder to add additional setters.
Yes, you can use Generics for this, but it needs a little twist. With the Type Parameter T extends Builder on the Base.Builder you allow derived Builders to specify that their type should be returned. The problem is, that this in the Base.Builder does not necessarily fulfill that requirement. So instead of using this to return in the setters, one has to pass/set the correct builder-instance to be returned using the method setBuilder. The derived Builder has to make sure to call super.setBuilder(this) at some point to make sure the Base.Builder is correctly initialized:
abstract class Base {
abstract static class Builder<T extends Builder> {
private int a;
private T builder;
protected void setBuilder(T builder) {
this.builder = builder;
}
T setA(int a) {
this.a = a;
return this.builder;
}
}
}
public class X extends Base {
static class Builder extends Base.Builder<Builder> {
public Builder() {
super.setBuilder(this);
}
X build() {
// Do some stuff with the configuration
return new X();
}
}
Builder builder() {
return new Builder();
}
}
Original Answer:
Yes, you can use Generics for this. Make the builder class take a Type parameter T extends Base, and add an abstract method T build() to it:
abstract class Base {
abstract static class Builder<T extends Base> {
private int a;
Builder<T> setA(int a) {
this.a = a;
return this;
}
abstract T build();
}
}
Now, extending classes can specify their type to the Builder and only have to overwrite the build method, and optionally provide additional setters:
public class X extends Base {
static class Builder extends Base.Builder<X> {
X build() {
// Do some stuff with the configuration
return new X();
}
}
}

Related

Is it possible to "adopt" a class as a child?

I'm currently writing a class, that should serve as an add-on to already existing classes. For example, let my add-on class be the following:
public class NewClass {}
Also, assume there already exist classes like:
public final class ExistingClassA {}
public final class ExistingClassB {}
...
These I am not allowed to change.
For some algorithms, I'd like to define the existing classes to be children of my NewClass, though. So instead of inherit from some class with extends, I kind of want to achieve the opposite: I want to "adopt" a class, as if the existing classes were originally defined this way:
public final class ExistingClassA extends NewClass {}
public final class ExistingClassB extends NewClass {}
...
Is this even possible in Java? And if so, is it also possible to add a class as a parent of a class, which already extends another class?
Edit:
To make my situation a bit clearer, I'll try describing what I want to achieve in more detail. E.g. assume a variable myVar, which should only be instance of specific classes. If those classes belonged to a common parent class, this wouldn't be a problem:
public final class ExistingClassA extends CommonParentClass {}
public final class ExisitingClassB extends CommonParentClass {}
public final class ExistingClassC extends CommonParentClass {}
...
/* We're inside some class now... */
CommonParentClass myVar; // May be of ExistingClassA, ExistingClassB, or ExistingClassC.
Now say, I want myVar to be only of the class ExistingClassA or ExistingClassB. Assuming I could "adopt" those two classes with my NewClass, I could also just write:
NewClass myVar; // May be of ExistingClassA, or ExistingClassB, but not ExistingClassC.
Since this seems not to be possible (from reading the comments), what approach would be the smartest to achieve the goal of just allowing myVar so be of a subset of CommonParentClass?
There's no compile-time mechanism to check whether a class extends either class A or B. If the authors of A and B did not define that they are related, they are not.
You have several options:
You could use instanceof and then cast to the specified type.
Object myObj = ...;
if (myObj instanceof Alpha) {
((Alpha) myObj).doSomething();
}
else if (myObj instanceof Bravo) {
((Bravo) myObj).doSomethingElse();
}
else {
throw new IllegalArgumentException("myObj" must be of either Alpha or Bravo");
}
Or you could make a wrapper object accepting either in the constructor:
class Either<A, B> {
A a;
B b;
boolean isA;
Either(A a) {
this.a = a;
this.isA = true;
}
Either(B b) {
this.b = b;
}
boolean isA() {
return isA;
}
A getA() {
return a;
}
B getB() {
return b;
}
}
and then call it:
Either<Alpha, Bravo> either = new Either(...);
if (either.isA()) {
either.getA().doSomething();
}
else {
either.getB().doSomethingElse();
}
But I fail to see how you want to use those two classes. Do they have a method with the same name? And why don't you just simply use two variables?

Java Returning Type of Child class (abstract)

I've been trying my best with some basic code, and I am completely stuck...
I have an abstract class "Piece":
public abstract class Piece {
private static int type;
public int getType() {
return type;
}
}
The "Pawn" is the Child:
public class Pawn extends Piece {
private static final int type = 1;
}
And now for the problem: When creating the Pawn with Pawn p = new Pawn();, p.getType() returns 0, not 1...
How can I fix this?
The problem is that you already have a variable declared in your abstract class. You shouldn't redeclare it in your subclass. Instead, set the abstract class's variable like this:
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
You should also declare the variable as protected so that subclasses can access it and refrain from making it static, since that will allow only one value for all subclasses:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
This code you write relies on an instance and not on a static context:
Pawn p = new Pawn();
p.getType();
A static final field is not designed to be inherited by child classes.
And creating a static final field in the child class with the same name as in the parent class doesn't allow to override it either.
1) So you should use an instance field and not a static field for the type field.
2) If you want to override the behavior of getType() in the child class, in fact you don't even need to use a field. Using a method should be enough.
In the base class :
public abstract class Piece {
public int getType() {
return 0;
}
}
In the child class :
public class Pawn extends Piece {
#Override
public int getType() {
return 1;
}
}
Here is one way. But you really need to read up on classes and abstract classes.
public abstract class Piece {
public int getType() {
return 0;
}
}
public class Pawn extends Piece {
public int getType() {
return 1;
}
}
Having a static variable in a class means that all instances of that class share the same value. I don't think that's what you intended.
Also, you can use the hierarchy of inheritance to your advantage by not redefining the getType() method.
Here is one of many ways to solve it:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
There are two problems with your approach.
The first is that Java does not support inheritance of static methods. Not that it couldn't have supported this - it's just a design choice. What this means is that any method of class Piece, which calls getType() - calls the Piece class' implementation of getType(), not a polymorphic call to getType() of whatever the actual subclass is.
The second problem is that you're sort of reinventing the wheel. Java has rich reflection facilities: You can use getClass() and instanceof for your check:
if(myObject instanceof Piece && myObject.getClass() != Piece.class) {
// do stuff
}
and of course you can make this a method of the piece class (no need to override it).

Is forcing a constructor signature a valid reason to use an abstract class rather than an interface?

For a project, I have written the following interface:
public interface IManipulation {
void applyManipulation (double value);
}
Since I would like to force all implementing classes to use a certain constructor signature, I have been considering to change the interface into something like the following abstract class:
(edit: I forgot that it's not possible to have an abstract constructor, so I changed the "solution" below a bit)
public abstract class Manipulation {
private Signal signal;
public Manipulation (Signal signal) {
this.signal = signal;
}
public abstract void applyManipulation (double value);
protected Signal getSignal () {
return signal;
}
}
The reason for wanting to force this constructor is because every implentation should have an instance of Signal available. (and it should not be possible to reassign this signal)
Is this a valid reason to replace the interface with an abstract class (and live with the limitations that come with it), or are there any other potential solutions?
instead of an abstract class you should use an init method for that purpose.
public interface MyInterface{
public void init(YourParam p);
//... other methods
}
in the init you check, if the class is allready initialised if yes, just return.
So you have still an interface and can extend from other classes.
Instead of the constructor you will call the init method for your initialization
EDIT:
public interface IManipulation {
void init(Signal s);
void applyManipulation (double value);
}
You should use abstract classes only, if you have implementation details in it, which are shared by all subclasses. For Method signatures use interfaces
You can make empty constructor private in the abstract class:
abstract class AbstractManipulation {
private final Integer signal;
private AbstractManipulation() {
signal = null;
}
public AbstractManipulation (Integer signal) {
this.signal = signal;
}
}
class Manipulation extends AbstractManipulation {
public Manipulation(Integer signal) {
super(signal);
}
// Cannot redeclare
//public Manipulation() {
//}
}
Then:
public static void main(String[] args) {
// Will not work
//Manipulation m = new Manipulation();
// This one will
Manipulation m = new Manipulation(1);
}
You should not choose for technical reasons but rather logical, ie an abstract class is used when you have a realtion with the sub-classes like for example person: student, teacher. An interface is used when you want to impose a service contract for classes that may not have a relationship between them.

Extending an abstract class with an abstract builder vs concrete class and concrete builder

I would like to use the builder pattern in some upcoming work that I have which has several classes in a hierarchy. The base class will have at least 9 fields to start, and the various sub-classes may add between 2-4 more fields each. This would get out of hand very quickly and the builder pattern is appealing to me for this exact reason. I got some initial exposure to the builder pattern in books and articles. They were helpful, but had nothing on how to extend this pattern. I tried to implement this by myself, but I ran into trouble with the constructors of each of the sub-classes because I didn't get how to pass the collected data in the builder to super class. I looked on SO for some answers, and here's what I found.
This one is from SO 24243240 where an example of how to extend an abstract class with an abstract builder is given. It is also based on this blog post.
public abstract class AbstractA {
protected String s;
protected int i;
protected AbstractA() {
}
protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
protected T object;
protected B thisObject;
protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
protected ABuilder() {
object = getObject();
thisObject = thisObject();
}
public B withS(String s) {
object.s = s;
return thisObject;
}
public B withI(int i) {
object.i = i;
return thisObject;
}
public T build() {
return object;
}
}
}
public final class ConcreteA extends AbstractA {
private String foo;
protected ConcreteA() {
}
public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
#Override protected ConcreteA getObject() {
return new ConcreteA();
}
#Override protected Builder thisObject() {
return this;
}
public Builder() {
}
public Builder withFoo(String foo) {
object.foo = foo;
return this;
}
}
}
And then in client code, it would look like...
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();
I like this example because it allows you to easily extend these classes, but it also seems to me that this defeats the purpose of using the builder pattern because the methods withS(String s) and withI(int i) act alot like setter methods. Also, this method leaves the fields of the base class and the builder class as protected rather than private.
Here's one from SO 17164375
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
I like that this one seemingly adheres more closely to the builder pattern described by Josh Bloch and it also allows you to simply pass the builder into the constructor for the class you want to instantiate. This would be a nice way to do some validation inside the builder before instantiating the object in the call to build(). At the same time though, this example shows how you can extend the builder pattern with concrete classes, and when you do that the potential for all the nastiness that comes with extending concrete classes (e.g. inconsistent interfaces, inheriting methods which can corrupt the state of your object, etc.)
So my question is there a way to implement an abstract class with an abstract builder that also allows you to pass in a reference to a builder in the constructor for the base class? Something like:
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
I realize that you can't instantiate an object the way that I've shown here, but is there some other way to do it I mean? Is this possibly where a factory would go? Maybe I just have the wrong assumptions about the builder pattern in general. :) If that's the case, is there a better direction to take?
Your first example is not bad, but I don't think it is what you are looking for.
I am still a little unsure of exactly what you want, but seeing your examples do not work for you, I thought I'd give you one or two of my own. :)
class ParentBuilder{
public ConcreteParent build(){
ConcreteParent parent = new ConcreteParent();
parent.setFirst(1);
parent.setSecond(2);
parent.setThird(3);
return parent;
}
}
class ChildBuilder{
public ConcreteChild build(ParentBuilder parentBuilder){
ConcreteParent parent = parentBuilder.build();
ConcreteChild child = new ConcreteChild();
child.setFirst(parent.getFirst());
child.setSecond(parent.getSecond());
child.setThird(parent.getThird());
child.setFourth(4); //Child specific value
child.setFifth(5); //Child specific value
return child;
}
}
Any new type, would have its own builder, taking in its parent's builder.
As you can see this is similar to:
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
In your example.
This however, quickly gets out of hand as well, increasingly for the number of variables and subclasses.
An alternativ, would be to use dynanic variables, have a look at this: http://martinfowler.com/apsupp/properties.pdf
Martin Fowler writes a great article specifying all the pros and cons.
Anyways, here's my second example:
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}
The magic here is, you (might) no longer need all these subclasses.
If these subclasses' behavior does not change, but only their variables, you should be fine using a system like this.
I strongly advise that you read Martin Fowler article on the subject though, there are good places and bad places to do this, but I think this is a good one.
I hope this brings you closer to an answer, good luck. :)

Can a super class method implementation depend on child class field

I am in a situation as follows.
I have an interface A which is inherited by class B,C,D (B,C,D implements A).
public interface A{
public String someMethod();
}
class B implements A{
ObjectType1 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
}
class C implements A{
ObjectType2 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
class D implements A{
ObjectType3 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
As you can see all method implementations are the same. So I am duplicating code. My plan was to move the method to A and make A an abstract class. But the problem is my method depends on the model field. So what would be my options to make this code better?
bdw class A,B,C extends and implements other classes too.
EDIT
modification in code. check field
I don't see any problem related to the model field transforming the interface A into an abstract class.
There is no need to reimplement the method in the subclasses if it is the same, unless you want to change its behavior (override it).
public abstract class A {
// Make it protected so it can accessible by subclasses
protected Object model;
// Common behavior that will be inherited by subclasses
public String someMethod() {
if (model instanceof X) {
return "x";
} else {
return "not x";
}
}
}
public class B extends A {
// Subclasses may access superclasses fields if protected or public.
public void someOtherMethod() {
System.out.println(super.model.toString());
}
}
public class C extends A {
// You may wish to override a parent's method behavior
#Override
public String someMethod() {
return "subclass implements it different";
}
}
For your new code example, if you really want to do that in a procedural way you can create an abstract superclass ObjectType and then it will be accessible for the parent as well.
However I wouldn't do that. It seems to me that in doing so is the very opposite of what object orientation tries to solve.
By using a subclass to define the behavior, you wouldn't need to do it in a procedural logic. That's precisely then point of using objects, inheritance and overriding/implementing behavior as needed.
Create a parent class A with said field, and said function. Have the other classes extend A. No need to override them if they function the same.
To deduplicate, you can either make A an abstract class and move the implementation of the method and the field there, or create an abstract class, say E, that implements the interface with that method and field and then have B, C and D extend that class E.
For the more general question of depending on a subclass's field, you can create an abstract method getModel which the subclasses decide how to implement -- by returning a model field or doing something else.
If you are using java 8 you could use default method in interface A, with a getter method for model.
public interface A{
default public String someMethod() {
if(getModel() instanceof X){
System.out.print(true);
}
}
public Object model getModel();
}
Then implement getModel method in all child interfaces.
If you're going to do this you must have model to be of the same (basic) type in all derived objects. If it were of the same type there's a case for putting the model to a base class. Anyway if they are of different derived types you would need to have an accessor to get it.
interface B {
BaseModel getModel();
default public strict doSomething() {
BaseModel m = getModel();
// do something with m
}
}
class D implements B {
DerivedModel model;
public getModel() {
return model;
}
}
If I was given a chance to refactor it, I will follow below approach, leveraging Java 8 Default Methods:
interface A {
default String someMethod(X objectType) {
if (objectType instanceof X) {
System.out.println(true);
}
// return something, for now returning class
return objectType.getClass().toString();
}
}
class B implements A {
#Override
public String someMethod(X objectType) {
if (objectType instanceof X) {
System.out.println(true);
}
// return "Hello"
return "Hello";
}
}
class C implements A {}
class D implements A {}
Usage:
public class Main implements A {
public static void main(String[] args) {
B b = new B();
C c = new C();
D d = new D();
Main main = new Main();
main.call(b);
main.call(c);
main.call(d);
}
public void call(A clazz) {
ObjectType1 objectType1 = new ObjectType1();
String type = clazz.someMethod(objectType1);
System.out.println(type);
}
}
interface X {
}
class ObjectType1 implements X {
}

Categories