I've got 3 interfaces:
public interface IAggregable<TElement extends IAggregable<TElement, TResult>, TResult> {
TResult aggregate(TResult intermediateResult);
}
public interface IDeeplyCloneable<TElement extends IDeeplyCloneable<TElement>> {
TElement deepClone();
}
public interface IContainer<TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> {
TResult aggregateAllElements();
TElement cloneElementAtIndex(int index);
}
Then there are two classes that implement those 2 first interfaces:
public class Person implements IAggregable<Person, Integer>, IDeeplyCloneable<Person> {
private int age;
public Integer aggregate(Integer intermediateResult) {
if (intermediateResult == null) {
return age;
}
return age + intermediateResult;
}
public Person deepClone() {
Person clone = new Person();
clone.age = age;
return clone;
}
#Override
public String toString() {
return "Person [age=" + age + "]";
}
}
and almost exactly the same
public class Car implements IAggregable<Car, Integer>, IDeeplyCloneable<Car> {
private int horsepower;
public Integer aggregate(Integer intermediateResult) {
if (intermediateResult == null) {
return horsepower;
}
return horsepower + intermediateResult;
}
public Car deepClone() {
Car clone = new Car();
clone.horsepower = horsepower;
return clone;
}
#Override
public String toString() {
return "Car [horsepower=" + horsepower + "]";
}
}
then there's finally UselessContainer which suppose to implement IContainer and be able to hold both Person and Car and any other objects of any other class that implements IAggregable and IDeeplyCloneable.
public class UselessContainer<TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> implements IContainer<TElement, TResult> {
private ArrayList<TElement> list;
public UselessContainer() {
this.list = new ArrayList<>();
}
public void add(TElement element) {
list.add(element);
}
#Override
public TResult aggregateAllElements() {
return null;
}
#Override
public TElement cloneElementAtIndex(int index) {
return null;
}
#Override
public String toString() {
return list.toString();
}
}
Question : How to create object of class UselessContainer?
I've tried that: UselessContainer<? extends IAggregable<?, Integer> & IDeeplyCloneable<?>, Integer> container;
You have marked your UselessContainer to be bound BOTH to IAggregable and IDeeplyCloneable. Please look at the & sign which indicates both of the interfaces must be implemented by business entity to be added to the list.
In order to use it in code - just create instance of UselessContainer without specyfing concrete generics types:
UselessContainer uc = new UselessContainer();
uc.add(new Person()); // works!
uc.add(new Integer(1)); // won't compile
uc.add(new Car()); // works!
I just tried it in my Editor and it works (JDK8).
EDIT:
You may create wrapping class:
class SimpleContainer {
public <TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> void add(TElement el) {
UselessContainer<TElement, TResult> uc = new UselessContainer<>();
uc.add(el);
}
}
and use it:
SimpleContainer sc = new SimpleContainer();
sc.add(new Person());
You have 2 conditions you want to meet for UselessContainer<A, B> (well shorten this to U<A,B>):
(1) Cars can be added to U<A, B>
(2) Persons can be added to U<A, B>
Fulfilling both (1) and (2) is impossible, which can be proven using a indirect proof:
Assume fulfilling both conditions was possible.
The signature of add is add(TElement element) method and TElement extends IAggregable<TElement, TResult>.
From (1) and Car implements IAggregable<Car, Integer> we can therefore deduce A=Car.
And from (2) and Person implements IAggregable<Person, Integer> we can therefore deduce A=Person.
Combining those 2 results we get Car=Person which is obviously wrong. This contradiction concludes the proof.
This means you have to modify the restrictions on the type parameters or use the raw type.
Related
Currently have an issue getting a specific object in an arraylist. So I have multiple classes that implements the same interface, and I create objects of the different classes. The problem is that I don't know how to differentiate the classes in the arraylist.
ArrayList<Interface> arraylist = new ArrayList<>();
public static void main(String[] args) {
addInterface(new interfaceA());
addInterface(new interfaceB());
addInterface(new interfaceC());
}
public static void addInterface(Interface foo) {
arraylist.add(foo);
}
Let say that I want to get interfaceA(), I could call it by arraylist.get(0) but I don't want to hardcode it. Each class has the same methods but the code is different.
I would use a Map instead of a List. In this case an IdentityHashMap is a good fit.
interface Thing {
}
IdentityHashMap<Class<? extends Thing>, Thing> things = new IdentityHashMap<>();
class ThingA implements Thing {
#Override
public String toString() {
return "ThingA{}";
}
}
class ThingB implements Thing {
#Override
public String toString() {
return "ThingB{}";
}
}
class ThingC implements Thing {
#Override
public String toString() {
return "ThingC{}";
}
}
public void registerThing(Thing thing) {
things.put(thing.getClass(), thing);
}
public void test(String[] args) {
registerThing(new ThingA());
registerThing(new ThingB());
registerThing(new ThingC());
System.out.println(things.get(ThingB.class));
}
You could filter using a predicate, by checking runtime classes:
List<Interface> interfaceAList = arraylist.stream()
.filter(e -> InterfaceA.class.isInstance(e))
.collect(Collectors.toList());
public Interface getInterfaceA(List<Interface> interfaces) {
for (Interface i : interfaces) {
if (i instanceof InterfaceA)
return i;
}
return null;
}
There are a lot of questions regarding Java methods returning generic types, but none of them helped me out so far.
So here's my code:
interface DAO<K, T> {
void insert(T t);
void update(K k, T t);
void delete(K k);
void delete();
T select(K k);
List<T> select();
}
public class CourseDAO implements DAO<String, Course> {
public void insert(Course t) {}
public void update(String k, Course t) {}
public void delete(String k) {}
public void delete() {}
public Course select(String k) {}
public List<Course> select() {}
}
public class StudentDAO implements DAO<Long, Student> {
public void insert(Student t) {}
public void update(Long k, Student t) {}
public void delete(Long k) {}
public void delete() {}
public Student select(Long k) {}
public List<Student> select() {}
}
public enum EntityType { COURSE, STUDENT }
Now I want a factory method which accepts an EntityType parameter and return an instance of CourseDAO or StudentDAO depending on the parameter value.
I tried the code below without success:
public <K,T> DAO<K,T> createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return (K,T) new CourseDAO(); break;
case STUDENT : return (K,T) new StudentDAO(); break;
}
return null;
}
Could anyone help me in writing and invoking this method???
Cheers,
Romualdo.
The cast you're looking for is (DAO<K,T>). But you'll get a warning because generic type erasure makes it unsafe. Another inherent risk in the switch factory is that you might forget to create a corresponding case when you add a new EntityType. A safer alternative would be to redefine EntityType with generic types, and let it be the factory. Unfortunately, this isn't possible with proper enums, but you can simulate it like this:
abstract class EntityType<K, T> {
public abstract DAO<K, T> createDAO();
public static final EntityType<String, Course> COURSE = new EntityType<String, Course>() {
#Override
public DAO<String, Course> createDAO() {
return new CourseDAO();
}
};
public static final EntityType<Long, Student> STUDENT = new EntityType<Long, Student>() {
#Override
public DAO<Long, Student> createDAO() {
return new StudentDAO();
}
};
}
Or you can use lambdas to reduce the boilerplate:
class EntityType<K, T> {
private final Supplier<DAO<K, T>> constructor;
private EntityType(Supplier<DAO<K, T>> constructor) {
this.constructor = constructor;
}
public DAO<K, T> createDAO() {
return constructor.get();
}
public static final EntityType<String, Course> COURSE = new EntityType<>(CourseDAO::new);
public static final EntityType<Long, Student> STUDENT = new EntityType<>(StudentDAO::new);
}
Now, instead of calling createDAOFactory(EntityType.COURSE), you would just call EntityType.COURSE.createDAO().
maybe you can do like this?
public class StudentDAO<Long,Student> implements DAO<Long, Student> {
public void insert(Student t) {}
public void update(Long k, Student t) {}
public void delete(Long k) {}
public void delete() {}
public Student select(Long k) {return null;}
public List<Student> select() {return null;}
}
public <K,T> DAO<K,T>createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return new CourseDAO();
case STUDENT : return new StudentDAO();
}
return null;
}
first answer
you do not need use generics,because Implementation class has specified the type.
public DAO createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return new CourseDAO();
case STUDENT : return new StudentDAO();
}
return null;
}
I have a class hierarchy like below
Vehicle
|_ TransaportationVehicle has method getLoadCapacity
|_ PassengerVehicle has method getPassengerCapacity
and I have one more class Booking it have a reference to Vehicle.
Now whenever I have to call getPassengerCapacity or getLoadCapacity on vehicle reference I need to type cast vehicle to its concrete implementation like ((PassengerVehicle)vehicle).getPassengerCapacity() and this type of calls spans over multiple parts in the project. So is there any way with which I can avoid these type of casts and my code will look beautiful and clean?
Note: These are not actual classes I have taken these as an example to demonstrate current problem.
Obviously, when booking a Vehicle you need to distinguish at some point whether it’s a TransportationVehicle or a PassengerVehicle as both have different properties.
The easiest way would be to initiate two different Booking processes: one for vehicles that can transport goods, and one for vehicles that can transport passengers. As for how to differentiate between these two types of vehicles: you could add canTransportPassengers() and canTransportGoods() methods to Vehicle, the subclasses would then override these methods to return true where appropriate. Also, this way a vehicle that can transport both is possible, like a train.
If You want to use different method names then You must cast to concrete class.
But if You can make this methods return same type value and have same names You can use polymorphism for it. Create abstract method in Vehicle class and override it in each child.
A quick way I would accomplish this is to create a Generified Booking parent class.
public abstract class Booking<V extends Vehicle> {
protected abstract V getVehicle();
}
public class TransportationVehicleBooking extends Booking<TransaportationVehicle> {
#Override
protected TransaportationVehicle getVehicle() {
return new TransaportationVehicle();
}
}
public class PassengerVehicleBooking extends Booking<PassengerVehicle> {
#Override
protected PassengerVehicle getVehicle() {
return new PassengerVehicle();
}
}
Your Booking class will have all the logic that spans all the booking subclasses and some abstract method each subclasses will need to do effective calculations.
Then all you have to do is have reference to a Booking class and calling the relevant method required without having to worry about the "logistics" (get it) of the booking itself.
I hope this helps.
You method overriding concepts. You need to have all these method in the Parent class and same can be overriden in the child clasees.
You can then access all the methods from super class using Runtime polymorphism
Vehicle
public interface Vehicle {
public int getCapacity();
}
TransaportationVehicle
public class TransaportationVehicle implements Vehicle {
#Override
public int getCapacity() {
return getLoadCapacity();
}
private int getLoadCapacity() {
return 0;
}
}
PassengerVehicle
public class PassengerVehicle implements Vehicle {
#Override
public int getCapacity() {
return getPassengerCapacity();
}
private int getPassengerCapacity() {
return 0;
}
}
USAGE
Vehicle passenger = new PassengerVehicle();
passenger.getCapacity();
Vehicle transaportation = new TransaportationVehicle();
transaportation.getCapacity()
First try to extract an abstract method suitable for all vehicles. If you can't do this you can also use an often forgotten pattern - the visitor pattern. E.g.
Introduce a visitor interface
public interface VehicleVisitor {
public void visit(TransportationVehicle transportationVehicle);
public void visit(PassengerVehicle passengerVehicle);
}
add an accept method to the Vehicle
public interface Vehicle {
public void accept(VehicleVisitor visitor);
}
implement the accept method in the sub classes
public class PassengerVehicle implements Vehicle {
private int passengerCapacity;
public static PassengerVehicle withPassengerCapacity(int passengerCapacity) {
return new PassengerVehicle(passengerCapacity);
}
private PassengerVehicle(int passengerCapacity) {
this.passengerCapacity = passengerCapacity;
}
public int getPassengerCapacity() {
return passengerCapacity;
}
#Override
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
public class TransportationVehicle implements Vehicle {
private int loadCapacity;
public static TransportationVehicle withLoadCapacity(int loadCapacity) {
return new TransportationVehicle(loadCapacity);
}
private TransportationVehicle(int loadCapacity) {
this.loadCapacity = loadCapacity;
}
public int getLoadCapacity() {
return loadCapacity;
}
#Override
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
implement a visitor...
public class LoadSupported implements VehicleVisitor {
private boolean supported;
private int load;
public LoadSupported(int load) {
this.load = load;
}
public boolean isSupported() {
return supported;
}
#Override
public void visit(TransportationVehicle transportationVehicle) {
int loadCapacity = transportationVehicle.getLoadCapacity();
supported = load <= loadCapacity;
}
#Override
public void visit(PassengerVehicle passengerVehicle) {
supported = false;
}
}
...and use it
public class Main {
public static void main(String[] args) {
TransportationVehicle transportationVehicle1 = TransportationVehicle
.withLoadCapacity(5);
TransportationVehicle transportationVehicle2 = TransportationVehicle
.withLoadCapacity(10);
PassengerVehicle passengerVehicle = PassengerVehicle
.withPassengerCapacity(5);
LoadSupported loadSupported = new LoadSupported(7);
supportsLoad(transportationVehicle1, loadSupported);
supportsLoad(transportationVehicle2, loadSupported);
supportsLoad(passengerVehicle, loadSupported);
}
private static void supportsLoad(Vehicle vehicle,
LoadSupported loadSupported) {
vehicle.accept(loadSupported);
System.out.println(vehicle.getClass().getSimpleName() + "[" + System.identityHashCode(vehicle) + "]" + " does"
+ (loadSupported.isSupported() ? " " : " not ")
+ "support load capacity");
}
}
The output will be something like this
TransportationVehicle[778966024] does not support load capacity
TransportationVehicle[1021653256] does support load capacity
PassengerVehicle[1794515827] does not support load capacity
Assuming that passenger capacity is always an integer and load capacity could very well a big number depending on what is the unit for load. I would go ahead and create Vehicle class as follow:
class Vehicle {
Number capacity;
public Number getCapacity() {
return capacity;
}
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
The reason I am using Number is so that I then use Integer in PassengerVehicle class and Double in TransporatationVehicle and that is because Integer and Double are subtype of Number and you can get away with a cast.
class TransportationVehicle extends Vehicle {
#Override
public Double getCapacity() {
//all I have to do is cast Number to Double
return (Double) capacity;
}
#Override
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
Similarly the PassengerVehicle class as follow:
class PassengerVehicle extends Vehicle {
#Override
public Integer getCapacity() {
//Cast to Integer and works because Integer is subtype of Number
return (Integer) capacity;
}
#Override
public void setCapacity(Number capacity) {
this.capacity = capacity;
}
}
You can then use above classes to create vehicle object as follow:
public class Booking {
public static void main(String[] args) {
//
Vehicle transportationVehicle = new TransportationVehicle();
//assigning Double to setCapacity
transportationVehicle.setCapacity(new Double(225.12));
Vehicle passengerVehicle = new PassengerVehicle();
//assigning Integer to setCapacity
passengerVehicle.setCapacity(5);
System.out.println(transportationVehicle.getCapacity());
// output: 225.12
System.out.println(passengerVehicle.getCapacity());
// output: 5
}
}
On the side notes if you try to pass TransportationVehicle anything but Number or Double then you will get Exception and similarly if you pass PassengerVehicle anything but Number or Integer you will get exception.
I know that I am deviating from the scope of your question but, I really want to show how you can make your methods generics. This allow you to decide to return type of getCapacity() during coding which is very flexible. See below:
class Vehicle<T> {
//generic type T
T capacity;
//generic method getCapacity
public T getCapacity() {
return capacity;
}
//generic method setCapacity
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
class TransportationVehicle<T> extends Vehicle<T> {
#Override
public T getCapacity() {
return capacity;
}
#Override
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
class PassengerVehicle<T> extends Vehicle<T> {
#Override
public T getCapacity() {
return capacity;
}
#Override
public void setCapacity(T capacity) {
this.capacity = capacity;
}
}
As you can see above the generic methods and you can use them as follow:
Vehicle<String> vehicleString = new TransportationVehicle<String>();
vehicleString.setCapacity("Seriously!"); //no problem
Vehicle<Integer> vehicleInteger = new PassengerVehicle<Integer>();
vehicleInteger.setCapacity(3); //boxing done automatically
Vehicle<Double> vehicleDouble = new PassengerVehicle<Double>();
vehicleDouble.setCapacity(2.2); //boxing done automatically
You can decide the type while coding and if you supply a Vehicle<String> with capacity as Integer then you will get compile time error, so you won't be allowed.
System.out.println(vehicleString.getCapacity());
//output: Seriously!
System.out.println(vehicleInteger.getCapacity());
//output: 3
System.out.println(vehicleDouble.getCapacity());
//output: 2.2
I don't understand the example. How do you realize that you are dealing with a concrete type in the first place? Are you instanceOf-ing? Are you type matching?
If so your problem is way past casting...
Anyways when you have objects that must belong to the same family and algorithms which are not abstract and change according to the object being handled you typically use some sort of behavioral pattern like visitor, or the Bridge pattern.
Hi I have very similar classes (Cars, Clients, Reservations). In those classes i have the same functions like ( add, delete, getItem, getAll and sort).
public class Clients {
List<Client> persons = new ArrayList<Client>();
public void add (Client k) {
persons.add(k);
}
public void delete (Client k) {
persons.remove(k);
}
public Client getKlienet(int id) {
for ( Client k: persons) {
if ( k.getId() == id)
return k;
}
return null;
}
public List<Client> getAllClients() {
List<Client> temp = new ArrayList<Client>();
temp.addAll(persons);
return temp;
}
public List<Client> sortujKontakty() {
Collections.sort(persons);
return persons;
}
I'd like to do with these classes one generic class. But i have a lot of problems..
First with function getId() (this function simply returns value of Id), and with sort() method. Compareto() methods are different for other classes.
So, i done interface:
public interface ManagerInterface <T> {
public void add (T t );
public void delete ( T t);
public T getRecord(int id);
public List<T> getAll();
public List<T> sort();
}
And class:
public class RecordManager<T> implements RecordManagerInterface <T> {
private T id;
public T getId() {
return id;
}
public ArrayList<T> record = new ArrayList<T>();
#Override
public void add(T t) {
record.add(t);
}
#Override
public void delete(T t) {
record.remove(t);
}
#Override
public T getRecord(int id) {
for ( T k: record) {
if ( ((Client) k).getId() == id)
return k;
else if ( ((Person) k).getId() == id)
return k;
else if ( ((Reservation) k).getId() == id)
return k;
}
return null;
}
#Override
public List<T> getAll() {
List<T> temp = new ArrayList<T>();
temp.addAll( record);
return temp;
}
#Override
public List<T> sort() {
Collections.sort(record);
return record;
}
Please for any help.
if you have similar classes, try to create common interface for them,
ie
interface HasId {
int getId();
}
then all what you need is make your classes to implement it, and change your RecordManager to be
public class RecordManager<T extends HasId> implements RecordManagerInterface <T> {
...
}
that means your T has to implement your interface,
so your get getRecord method will be much simpler
public T getRecord(int id) {
for ( T k: record) {
if (k.getId() == id)
return k;
}
return null;
}
EDIT
Lets say your common interface will be
interface CommonInterface<T> extends Comparable<T> {
public int getId();
}
then definition of your class will be, ie
Person implements CommonInterface<Person> {
...
}
your RecordManager
class RecordManager<T extends CommonInterface<T>> implements
RecordManagerInterface<T>{
}
and that should fix all your problems with sort
This is what is called "coding to the interface". Then when you instantiate the objects, make your reference to the interface and the object to the specific class you want to instantiate.
Ex:
Interface example = new Class();
Then use example.getMethod(), example.setMethod(). This will actually call the Class.getMethod() if it has one, as per inheritance.
Give this Dr Dobbs article, and the Builder Pattern in particular, how do we handle the case of subclassing a Builder? Taking a cut-down version of the example where we want to subclass to add GMO labelling, a naive implementation would be:
public class NutritionFacts {
private final int calories;
public static class Builder {
private int calories = 0;
public Builder() {}
public Builder calories(int val) { calories = val; return this; }
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
Subclass:
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.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;
}
}
Now, we can write code like this:
GMOFacts.Builder b = new GMOFacts.Builder();
b.GMO(true).calories(100);
But, if we get the order wrong, it all fails:
GMOFacts.Builder b = new GMOFacts.Builder();
b.calories(100).GMO(true);
The problem is of course that NutritionFacts.Builder returns a NutritionFacts.Builder, not a GMOFacts.Builder, so how do we solve this problem, or is there a better Pattern to use?
Note: this answer to a similar question offers up the classes I have above; my question is regarding the problem of ensuring the builder calls are in the correct order.
You can solve it using generics. I think this is called the "Curiously recurring generic patterns"
Make the return type of the base class builder methods a generic argument.
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder<T>> {
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;
}
}
Now instantiate the base builder with the derived class builder as the generic argument.
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;
}
}
Just for the record, to get rid of the
unchecked or unsafe operations warning
for the return (T) this; statement as #dimadima and #Thomas N. talk about, following solution applies in certain cases.
Make abstract the builder which declares the generic type (T extends Builder in this case) and declare protected abstract T getThis() abstract method as follows:
public abstract static class Builder<T extends Builder<T>> {
private int calories = 0;
public Builder() {}
/** The solution for the unchecked cast warning. */
public abstract T getThis();
public T calories(int val) {
calories = val;
// no cast needed
return getThis();
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
Refer to http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ205 for further details.
Based off of a blog post, this approach requires all the non-leaf classes to be abstract, and all the leaf classes must be final.
public abstract class TopLevel {
protected int foo;
protected TopLevel() {
}
protected static abstract class Builder
<T extends TopLevel, B extends Builder<T, B>> {
protected T object;
protected B thisObject;
protected abstract T createObject();
protected abstract B thisObject();
public Builder() {
object = createObject();
thisObject = thisObject();
}
public B foo(int foo) {
object.foo = foo;
return thisObject;
}
public T build() {
return object;
}
}
}
Then, you have some intermediate class that extends this class and its builder, and as many more as you need:
public abstract class SecondLevel extends TopLevel {
protected int bar;
protected static abstract class Builder
<T extends SecondLevel, B extends Builder<T, B>> extends TopLevel.Builder<T, B> {
public B bar(int bar) {
object.bar = bar;
return thisObject;
}
}
}
And, finally a concrete leaf class that can call all the builder methods on any of its parents in any order:
public final class LeafClass extends SecondLevel {
private int baz;
public static final class Builder extends SecondLevel.Builder<LeafClass,Builder> {
protected LeafClass createObject() {
return new LeafClass();
}
protected Builder thisObject() {
return this;
}
public Builder baz(int baz) {
object.baz = baz;
return thisObject;
}
}
}
Then, you can call the methods in any order, from any of the classes in the hierarchy:
public class Demo {
LeafClass leaf = new LeafClass.Builder().baz(2).foo(1).bar(3).build();
}
You can override also the calories() method, and let it return the extending builder. This compiles because Java supports covariant return types.
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder {
private boolean hasGMO = false;
public Builder() {
}
public Builder GMO(boolean val)
{ hasGMO = val; return this; }
public Builder calories(int val)
{ super.calories(val); return this; }
public GMOFacts build() {
return new GMOFacts(this);
}
}
[...]
}
There is also another way to create classes according to Builder pattern, which conforms "Prefer composition over inheritance".
Define an interface, that parent class Builder will inherit:
public interface FactsBuilder<T> {
public T calories(int val);
}
The implementation of NutritionFacts is almost the same (except for Builder implementing 'FactsBuilder' interface):
public class NutritionFacts {
private final int calories;
public static class Builder implements FactsBuilder<Builder> {
private int calories = 0;
public Builder() {
}
#Override
public Builder calories(int val) {
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
The Builder of a child class should extend the same interface (except different generic implementation):
public static class Builder implements FactsBuilder<Builder> {
NutritionFacts.Builder baseBuilder;
private boolean hasGMO = false;
public Builder() {
baseBuilder = new NutritionFacts.Builder();
}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() {
return new GMOFacts(this);
}
#Override
public Builder calories(int val) {
baseBuilder.calories(val);
return this;
}
}
Notice, that NutritionFacts.Builder is a field inside GMOFacts.Builder (called baseBuilder). The method implemented from FactsBuilder interface calls baseBuilder's method of the same name:
#Override
public Builder calories(int val) {
baseBuilder.calories(val);
return this;
}
There is also a big change in the constructor of GMOFacts(Builder builder). The first call in the constructor to parent class constructor should pass appropriate NutritionFacts.Builder:
protected GMOFacts(Builder builder) {
super(builder.baseBuilder);
hasGMO = builder.hasGMO;
}
The full implementation of GMOFacts class:
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder implements FactsBuilder<Builder> {
NutritionFacts.Builder baseBuilder;
private boolean hasGMO = false;
public Builder() {
}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() {
return new GMOFacts(this);
}
#Override
public Builder calories(int val) {
baseBuilder.calories(val);
return this;
}
}
protected GMOFacts(Builder builder) {
super(builder.baseBuilder);
hasGMO = builder.hasGMO;
}
}
A full 3 level example of multiple builder inheritance would look like this:
(For the version with a copy constructor for the builder see the second example below)
First level - parent (potentially abstract)
import lombok.ToString;
#ToString
#SuppressWarnings("unchecked")
public abstract class Class1 {
protected int f1;
public static class Builder<C extends Class1, B extends Builder<C, B>> {
C obj;
protected Builder(C constructedObj) {
this.obj = constructedObj;
}
B f1(int f1) {
obj.f1 = f1;
return (B)this;
}
C build() {
return obj;
}
}
}
Second level
import lombok.ToString;
#ToString(callSuper=true)
#SuppressWarnings("unchecked")
public class Class2 extends Class1 {
protected int f2;
public static class Builder<C extends Class2, B extends Builder<C, B>> extends Class1.Builder<C, B> {
public Builder() {
this((C) new Class2());
}
protected Builder(C obj) {
super(obj);
}
B f2(int f2) {
obj.f2 = f2;
return (B)this;
}
}
}
Third level
import lombok.ToString;
#ToString(callSuper=true)
#SuppressWarnings("unchecked")
public class Class3 extends Class2 {
protected int f3;
public static class Builder<C extends Class3, B extends Builder<C, B>> extends Class2.Builder<C, B> {
public Builder() {
this((C) new Class3());
}
protected Builder(C obj) {
super(obj);
}
B f3(int f3) {
obj.f3 = f3;
return (B)this;
}
}
}
And an example of usage
public class Test {
public static void main(String[] args) {
Class2 b1 = new Class2.Builder<>().f1(1).f2(2).build();
System.out.println(b1);
Class2 b2 = new Class2.Builder<>().f2(2).f1(1).build();
System.out.println(b2);
Class3 c1 = new Class3.Builder<>().f1(1).f2(2).f3(3).build();
System.out.println(c1);
Class3 c2 = new Class3.Builder<>().f3(3).f1(1).f2(2).build();
System.out.println(c2);
Class3 c3 = new Class3.Builder<>().f3(3).f2(2).f1(1).build();
System.out.println(c3);
Class3 c4 = new Class3.Builder<>().f2(2).f3(3).f1(1).build();
System.out.println(c4);
}
}
A bit longer version featuring a copy constructor for the builder:
First level - parent (potentially abstract)
import lombok.ToString;
#ToString
#SuppressWarnings("unchecked")
public abstract class Class1 {
protected int f1;
public static class Builder<C extends Class1, B extends Builder<C, B>> {
C obj;
protected void setObj(C obj) {
this.obj = obj;
}
protected void copy(C obj) {
this.f1(obj.f1);
}
B f1(int f1) {
obj.f1 = f1;
return (B)this;
}
C build() {
return obj;
}
}
}
Second level
import lombok.ToString;
#ToString(callSuper=true)
#SuppressWarnings("unchecked")
public class Class2 extends Class1 {
protected int f2;
public static class Builder<C extends Class2, B extends Builder<C, B>> extends Class1.Builder<C, B> {
public Builder() {
setObj((C) new Class2());
}
public Builder(C obj) {
this();
copy(obj);
}
#Override
protected void copy(C obj) {
super.copy(obj);
this.f2(obj.f2);
}
B f2(int f2) {
obj.f2 = f2;
return (B)this;
}
}
}
Third level
import lombok.ToString;
#ToString(callSuper=true)
#SuppressWarnings("unchecked")
public class Class3 extends Class2 {
protected int f3;
public static class Builder<C extends Class3, B extends Builder<C, B>> extends Class2.Builder<C, B> {
public Builder() {
setObj((C) new Class3());
}
public Builder(C obj) {
this();
copy(obj);
}
#Override
protected void copy(C obj) {
super.copy(obj);
this.f3(obj.f3);
}
B f3(int f3) {
obj.f3 = f3;
return (B)this;
}
}
}
And an example of usage
public class Test {
public static void main(String[] args) {
Class3 c4 = new Class3.Builder<>().f2(2).f3(3).f1(1).build();
System.out.println(c4);
// Class3 builder copy
Class3 c42 = new Class3.Builder<>(c4).f2(12).build();
System.out.println(c42);
Class3 c43 = new Class3.Builder<>(c42).f2(22).f1(11).build();
System.out.println(c43);
Class3 c44 = new Class3.Builder<>(c43).f3(13).f1(21).build();
System.out.println(c44);
}
}
If you don't want to poke your eye out on an angle bracket or three, or perhaps don't feel you... umm... I mean... cough... the rest of your team will quickly comprehend curiously recurring generics pattern, you can do this:
public class TestInheritanceBuilder {
public static void main(String[] args) {
SubType.Builder builder = new SubType.Builder();
builder.withFoo("FOO").withBar("BAR").withBaz("BAZ");
SubType st = builder.build();
System.out.println(st.toString());
builder.withFoo("BOOM!").withBar("not getting here").withBaz("or here");
}
}
supported by
public class SubType extends ParentType {
String baz;
protected SubType() {}
public static class Builder extends ParentType.Builder {
private SubType object = new SubType();
public Builder withBaz(String baz) {
getObject().baz = baz;
return this;
}
public Builder withBar(String bar) {
super.withBar(bar);
return this;
}
public Builder withFoo(String foo) {
super.withFoo(foo);
return this;
}
public SubType build() {
// or clone or copy constructor if you want to stamp out multiple instances...
SubType tmp = getObject();
setObject(new SubType());
return tmp;
}
protected SubType getObject() {
return object;
}
private void setObject(SubType object) {
this.object = object;
}
}
public String toString() {
return "SubType2{" +
"baz='" + baz + '\'' +
"} " + super.toString();
}
}
and the parent type:
public class ParentType {
String foo;
String bar;
protected ParentType() {}
public static class Builder {
private ParentType object = new ParentType();
public ParentType object() {
return getObject();
}
public Builder withFoo(String foo) {
if (!"foo".equalsIgnoreCase(foo)) throw new IllegalArgumentException();
getObject().foo = foo;
return this;
}
public Builder withBar(String bar) {
getObject().bar = bar;
return this;
}
protected ParentType getObject() {
return object;
}
private void setObject(ParentType object) {
this.object = object;
}
public ParentType build() {
// or clone or copy constructor if you want to stamp out multiple instances...
ParentType tmp = getObject();
setObject(new ParentType());
return tmp;
}
}
public String toString() {
return "ParentType2{" +
"foo='" + foo + '\'' +
", bar='" + bar + '\'' +
'}';
}
}
Key points:
Encapsulate the object in the builder so that inheritance prevents you from setting the field on the object held in the parent type
Calls to super ensure that logic (if any) added to the super type builder methods is retained in the sub types.
Down side is spurious object creation in the parent class(es)... But see below for a way to clean that up
Up side is much easier to understand at a glance, and no verbose constructor transferring properties.
If you have multiple threads accessing your builder objects... I guess I'm glad I'm not you :).
EDIT:
I found a way around the spurious object creation. First add this to each builder:
private Class whoAmI() {
return new Object(){}.getClass().getEnclosingMethod().getDeclaringClass();
}
Then in the constructor for each builder:
if (whoAmI() == this.getClass()) {
this.obj = new ObjectToBuild();
}
The cost is an extra class file for the new Object(){} anonymous inner class
One thing you could do is to create a static factory method in each of your classes:
NutritionFacts.newBuilder()
GMOFacts.newBuilder()
This static factory method would then return the appropriate builder. You can have a GMOFacts.Builder extending a NutritionFacts.Builder, that is not a problem. THE problem here will be to deal with visibility...
I created a parent, abstract generic builder class that accepts two formal type parameters. First is for the type of object returned by build(), the second is the type returned by each optional parameter setter. Below are parent and child classes for illustrative purpose:
// **Parent**
public abstract static class Builder<T, U extends Builder<T, U>> {
// Required parameters
private final String name;
// Optional parameters
private List<String> outputFields = null;
public Builder(String pName) {
name = pName;
}
public U outputFields(List<String> pOutFlds) {
outputFields = new ArrayList<>(pOutFlds);
return getThis();
}
/**
* This helps avoid "unchecked warning", which would forces to cast to "T" in each of the optional
* parameter setters..
* #return
*/
abstract U getThis();
public abstract T build();
/*
* Getters
*/
public String getName() {
return name;
}
}
// **Child**
public static class Builder extends AbstractRule.Builder<ContextAugmentingRule, ContextAugmentingRule.Builder> {
// Required parameters
private final Map<String, Object> nameValuePairsToAdd;
// Optional parameters
private String fooBar;
Builder(String pName, Map<String, String> pNameValPairs) {
super(pName);
/**
* Must do this, in case client code (I.e. JavaScript) is re-using
* the passed in for multiple purposes. Doing {#link Collections#unmodifiableMap(Map)}
* won't caught it, because the backing Map passed by client prior to wrapping in
* unmodifiable Map can still be modified.
*/
nameValuePairsToAdd = new HashMap<>(pNameValPairs);
}
public Builder fooBar(String pStr) {
fooBar = pStr;
return this;
}
#Override
public ContextAugmentingRule build() {
try {
Rule r = new ContextAugmentingRule(this);
storeInRuleByNameCache(r);
return (ContextAugmentingRule) r;
} catch (RuleException e) {
throw new IllegalArgumentException(e);
}
}
#Override
Builder getThis() {
return this;
}
}
This one has met my needs to satisfaction.
The following IEEE contribution Refined Fluent Builder in Java gives a comprehensive solution to the problem.
It dissects the original question into two sub-problems of inheritance deficiency and quasi invariance and shows how a solution to these two sub-problems opens for inheritance support with code reuse in the classical builder pattern in Java.