Results 1 to 10 of 10
  1. #1
    Join Date
    Jul 2008
    Posts
    7
    Rep Power
    0

    Default 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 06:40 PM. Reason: mistaken code

  2. #2
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,224
    Rep Power
    20

    Default

    What is your problem though?
    You haven't actually told us (unless I'm missing it).

  3. #3
    Join Date
    Jul 2008
    Posts
    7
    Rep Power
    0

    Default

    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

  4. #4
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    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>>();

  5. #5
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,224
    Rep Power
    20

    Default

    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.

  6. #6
    Join Date
    Jul 2008
    Posts
    7
    Rep Power
    0

    Default

    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?

  7. #7
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,224
    Rep Power
    20

    Default

    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.
        }
    }

  8. #8
    Join Date
    Jul 2008
    Posts
    7
    Rep Power
    0

    Default

    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

  9. #9
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    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?

  10. #10
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,224
    Rep Power
    20

    Default

    Quote Originally Posted by sideswipe091976 View Post
    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
    A.add(b) is fine, since add() expects an A, and B is an A.

    But if the type of the List was List<List<A>>, then you could not add() a List<B> to it.

Similar Threads

  1. Generics and wildcards confusion
    By castiel in forum New To Java
    Replies: 7
    Last Post: 02-23-2011, 04:37 AM
  2. Java i/o confusion
    By willemien in forum New To Java
    Replies: 1
    Last Post: 02-11-2011, 02:35 PM
  3. java API (SE) version confusion
    By Arnold in forum New To Java
    Replies: 3
    Last Post: 04-30-2010, 11:42 AM
  4. confusion with Design Pttern in java
    By sandeepsai39 in forum New To Java
    Replies: 2
    Last Post: 11-23-2009, 08:45 AM
  5. Java N00B - Remote Assistance Invitations
    By victimist in forum Java Applets
    Replies: 6
    Last Post: 10-25-2008, 02:30 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •