Results 1 to 10 of 10
- 03-24-2011, 09:36 PM #1
Member
- Join Date
- Jul 2008
- Posts
- 7
- Rep Power
- 0
Java Generics assistance and confusion
I am hoping someone can help me with this. Browsing around the net doesn't I didn't find my case. Just some input.
Scenario:
I have a chain of responsibility and use a composite responsibility to that end.
Most responsibilities in the series can act on the interface level type of the object (in this case, Alert) but some must have a specific type to really be valid (SubscriptionAlert).
In the special cases, specifying the most restrictive type should work fine and yet I get a variety of problems. It's my own ignorance for sure. Here are the classes:
public interface Responsibility<T extends Alert> {
public void perform(T t);
}
public class CompositeResponsibility<T extends Alert> implements Responsibility<T>{
private List<Responsibility<T>> responsibilities = new LinkedList<Responsibility<T>>();
public CompositeResponsibility(List<Responsibility<T>> responsibilities) {
this.responsibilities = responsibilities;
}
public CompositeResponsibility() {
}
public CompositeResponsibility(Responsibility<T> ... responsibilities) {
this.responsibilities = Arrays.asList(responsibilities);
}
public boolean add(Responsibility<T> r) {
return this.responsibilities.add(r);
}
public boolean remove(Responsibility<T> r) {
return this.responsibilities.remove(r);
}
public List<Responsibility<T>> getResponsibilities() {
return responsibilities;
}
public void setResponsibilities(List<Responsibility<T>> responsibilities) {
this.responsibilities = responsibilities;
}
@Override
public void perform(T t) {
for (Responsibility<T> r : responsibilities)
r.perform(t);
}
}
public class ValidationResponsibility implements Responsibility<Alert> {
...
}
public class SendSubscribeNoticeResponsibility implements Responsibility<SubscriptionAlert> {
...
}
@Test
public void testTopUp() throws Exception {
CompositeResponsibility<Alert> comp = new CompositeResponsibility<Alert>();
comp.add(new KeyInjectResponsibility());
comp.add(new ValidationResponsibility());
comp.add(new SendSubscribeNoticeResponsibility()); // problem here
}Last edited by sideswipe091976; 03-25-2011 at 05:40 PM. Reason: mistaken code
- 03-25-2011, 09:19 AM #2
Moderator
- Join Date
- Apr 2009
- Posts
- 10,481
- Rep Power
- 16
What is your problem though?
You haven't actually told us (unless I'm missing it).
- 03-25-2011, 05:39 PM #3
Member
- Join Date
- Jul 2008
- Posts
- 7
- Rep Power
- 0
Last line of code indicates the problem. Sorry for not being clearer.
I am updating the original post to give more info
error: add(Responsibility<Alert>) in CompositeResponsibility<Alert> cannot be applied to (SendSubscribeNoticeResponsibility)
In essence it isn't allowing me to add the last responsibility
- 03-26-2011, 04:52 AM #4
Senior Member
- Join Date
- Jan 2009
- Posts
- 671
- Rep Power
- 5
comp is of type CompositeResponsibility<Alert>
comp.responsibilities is of type LinkedList<Responsibility<Alert>>
SendSubscribeNoticeResponsibility is of type Responsibility<SubscriptionAlert>.
You haven't shown what a SubscriptionAlert is, but I'm guessing it is a subclass of Alert?
Anyway, I think the problem is that the compiler is allowing for T to be a lower level than Alert. For example, T could be a BogusAlert. If it were, then it would not necessarily be valid to insert a SubscriptionAlert into a LinkedList of type BogusAlert.
I *think* that you are wanting 'responsibilities' to always be a LinkedList of type Responsibility<Alert>? If so, then declare it that way:
Java Code:private List<Responsibility<Al;ert>> responsibilities = new LinkedList<Responsibility<Alert>>();
- 03-28-2011, 09:25 AM #5
Moderator
- Join Date
- Apr 2009
- Posts
- 10,481
- Rep Power
- 16
OK.
A Responsibility<SubscriptionAlert> is not at all related to a Responsibility<Alert>.
Consequently inheritance etc plays no part here, so you cannot pass in a Responsibility<SubscriptionAlert> into something expecting a Responsibility<Alert>.
It's a common mistake.
- 03-29-2011, 04:00 PM #6
Member
- Join Date
- Jul 2008
- Posts
- 7
- Rep Power
- 0
Checkout CompositeResponsibility signature and first member. This is more or less what you suggest. I mean, that's my thinking. Basically, it can accept Alert or any subclass thereof.
public class CompositeResponsibility<T extends Alert> implements Responsibility<T>{
private List<Responsibility<T>> responsibilities = new LinkedList<Responsibility<T>>();
So, here is a test case:
@Test
public void testGenerics() throws Exception {
CompositeResponsibility<SubscriptionAlert> comp = new CompositeResponsibility<SubscriptionAlert>();
comp.add(new KeyInjectResponsibility()); //KeyInjectResponsibility<Alert>
comp.add(new SendSubscribeNoticeResponsibility()); // SendSubscribeNoticeResponsibility<SubscriptionNoti ce>
}
SubscriptionAlert is an Alert. The first responsibility can act on it no problem. But in this scenario it complains on the first responsibility.
I mean, if I declared the 'perform' method to be 'perform(Alert a)' instead of using a generic of type <T extends Alert> this would work all day. I may want to reuse this and thus would like to use generics.
Tolls, to your point, isn't that what " extends XXX" is for? I am trying to understand this better -- I don't mean to be hard headed. Assuming all you say is true, then how do I accomplish that which I seek? I want the entire stack of responsibilities limited to only accepting a SubscriptionAlert. What needs to change to make that happen?
- 03-29-2011, 04:17 PM #7
Moderator
- Join Date
- Apr 2009
- Posts
- 10,481
- Rep Power
- 16
That extends merely says that a Responsibility can only be defined in terms of something that extends Alert. It does not say a Responsibility<SubscriptionAlert> extends a Responsibility<Alert>.
In the same vein, you cannot cast a List<A> to a List<B> in the following example:
Java Code:class A { } class B extends A { } class C { public void methodABC() { List<A> A = new ArrayList<A>(); List<B> B = new ArrayList<B>(); A = B; // compilation error since List<B> is not a List<A>. A a = new A(); B b = new B(); a = b; // But this works as expected. } }
- 03-29-2011, 05:50 PM #8
Member
- Join Date
- Jul 2008
- Posts
- 7
- Rep Power
- 0
Ok, how about
A.add(b);
As the last line. How do you make that work? B is of type A and it polymorphically allowable
- 03-29-2011, 11:28 PM #9
Senior Member
- Join Date
- Jan 2009
- Posts
- 671
- Rep Power
- 5
sideswipe, a List<Responsibility<T extends Alert>> is not the same as List<Responsibility<Alert>>.
As I tried to explain above, if T is 'BogusAlert' which extends Alert, and 'SubscriptionAlert' also extends Alert, but does not extend BogusAlert, can you see that it would not make sense to allow a SubscriptionAlert to be inserted? Did you try changing the code as I suggested previously? If not, why not?
- 03-30-2011, 08:24 AM #10
Moderator
- Join Date
- Apr 2009
- Posts
- 10,481
- Rep Power
- 16
Similar Threads
-
Generics and wildcards confusion
By castiel in forum New To JavaReplies: 7Last Post: 02-23-2011, 03:37 AM -
Java i/o confusion
By willemien in forum New To JavaReplies: 1Last Post: 02-11-2011, 01:35 PM -
java API (SE) version confusion
By Arnold in forum New To JavaReplies: 3Last Post: 04-30-2010, 10:42 AM -
confusion with Design Pttern in java
By sandeepsai39 in forum New To JavaReplies: 2Last Post: 11-23-2009, 07:45 AM -
Java N00B - Remote Assistance Invitations
By victimist in forum Java AppletsReplies: 6Last Post: 10-25-2008, 01:30 AM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks