I am playing with using generics to be able to restrict sub-types in a composite hierarchy, so that I could force different types at different layers of a hierarchy.
For example having a (Business:Division:Department:Group:Person) hierarchy, where the composite nodes at each level would only accept child nodes of the proper type (the next lower level in the hierarchy). So I would construct the levels in the composite using generics at each level type instantiated to accept only nodes from the next lower level.
But I get an error with the generics, and am not sure if it indicates a design error, or just something that java Generics can't do for me. The idea seems valid, I just want to restrict the types accepted by the add() methods to only accept a sub-type from the specific next level in the hierarchy to force the levels of structure. Since I am just lowering the upper-bound on the type at each stage, all messages sent to the list would still be valid.
Top level node in the typical GOF-Composite pattern:
public abstract class Business { ... }
Composite node hierarchy top level:
public abstract class Group extends Business {
protected List<Business> subs; // composite links
public Group add(Business comp) {
subs.add(comp);
return this;
}
Subsequent levels in the composite hierarchy:
public class Area<T extends Business> extends Group {
protected List<Business> subs; // composite links
public Area(String title){
super(title);
subs = new ArrayList<Business>();
}
@Override
public Group add(T comp) { // ** Error Here **
super.add(comp);
return this;
}
The Error is:
Multiple markers at this line - The method add(T) of type Area<T> must override a superclass method
- Name clash: The method add(T) of type Area has the same erasure as add(Business) of type Group but does not override it
I tried a variation where I gave a similar type to the Group::add() method so they would have the same type signatures,
public Group add(T comp) { ... }
But that fails similarly:
Multiple markers at this line
- The method add(T) of type Area must override a superclass method - overrides labs.composite.company.Group.add - Name clash: The method add(T) of type Area has the same erasure as add(T) of type Group but does not override it
Am I missing something here??? TIA
PS: Actually I think that this use of generics does not do exactly what I want anyway (even if it did work!), since i want to not only change the upper-bound at each level, but require a specific single level in the type hierarchy, not any covariant argument type. I really would want something like, "for any type T which is a sub-type of Composite, accept only that type of object in the add() method", I think that instead the generics says "accept any object as an argument which is a subtype of Composite". I suppose that is impossible since arguments in Java are covariant, and LSP will always allow sub-types to be used.