If your question is why the error, the reason is simple: T
in Area
can be an infinitude of Business
subclasses, while Business
in Group
is a very specific class. Both methods are not the same. The compiler works mainly with full types while performing type checking (even if it also considers erasures for certain kind of warnings and special cases). That's the whole point of generics. Otherwise, it's better to revert to pre-generics code style (which is still supported).
If not, then I don't understand the question. But let me add a few more comments:
1) Inheritance describes a "is a kind of" relationship, not a "has" or "is composed of" relationship. In the code, you are saying that a Group
is a kind of Business
, and that an Area
is a kind of Group
. To me, it's much more natural to think that a Group
belongs to a Business
(i.e. a Business
has Group
s). Same thing with Group
s and Area
s. None of these two relationships are of inheritance, but of composition.
2) When in class Group<T extends Business>
you define method add(T comp)
and in class Area<T extends Business>
you define method add(T comp)
, you say Group::add
and Area:add
have the same signature. That's not correct. The generic parameter T
in Group is completely independent of the T
in Area. Why? Assume that B1
and B2
are subclasses of Bussiness, but not of each other. Nobody can say that Area<B1>:add()
and Group<B2>:add()
have the same signature. In fact, the only case when this equivalence holds is when the generic argument is the same (i.e. Area<B1>
and Group<B1>
). Java can not consider the signatures equivalent when that equivalency holds only in a few particular cases (that are not otherwise described by the code).
3) GOF's Composite design pattern does not apply to this case because it does not represent hierarchical composition, but what we could call "unrestricted" composition. According to this pattern, aComposite
can contain differentComponents
, but these Component
s can be any kind of Composite
s, regardless of how high or low in a class hierarchy. What you want is differentComponents
to be of the immediately lower class. No more, and no less.
I don't remember to have seen this case as a design pattern. Probably because it's too simple. See the last variant in next point 4).
4) Your code should probably take the following form:
public class Grouping<C,T> {
C curr;
List<T> subs;
public C add(T comp) {
this.subs.add(comp);
return this.curr ;
}
}
public class Business extends Grouping<Business,Group> {
// Grouping::add does not need to be overriden
}
public class Group extends Grouping<Group,Area> {
// Grouping::add does not need to be overriden
}
And so on. If you allow method add
to return void
instead of C
, you can eliminate a generic parameter in all classes:
public class Grouping<T> {
List<T> subs;
public void add(T comp) {
this.subs.add(comp);
}
}
public class Business extends Grouping<Group> {
// Grouping::add does not need to be overriden
}
public class Group extends Grouping<Area> {
// Grouping::add does not need to be overriden
}
And if you want to make it really simple (but perhaps not as powerful):
public class Business {
List<Group> subs;
public Business add(Group comp) {
this.subs.add(comp);
return this ;
}
}
public class Group {
List<Area> subs;
public Group add(Area comp) {
this.subs.add(comp);
return this ;
}
}
This creates code duplication (method add
in every class) that under more realistic scenarios could be much higher (you could also want methods count
, list
, retrieve
, etc).