Domanda

So I have this Java code:

public <A extends Action> List<A> getActionsFor(Actor a) {
    List<A> theActions = super.getActionsFor(a);

    for (Action ac: a.getItemCarried().getActions()) {
        theActions.add(ac);
    }

    return theActions;
}

For some reason javac is rejecting the .add(ac) claiming add(A) cannot be applied to Action.

Am I missing something key here? I can work around this by creating dependencies across two packages but I really do not want to do that.

All classes in question have been imported correctly, and each method called works, so I am really lost as to why it can't accept the class type that A extends.

Any suggestions even if you aren't sure would be appreciated as I have to get this fixed within the next 6 hours, otherwise I'll need to create that dependency.

È stato utile?

Soluzione

Am I missing something key here?

A is something which extends Action, ac is also something which extends Action. However this is a bit like the facility

Yesterday I saw someone.
Someone is the President
Therefor, yesterday I was the President.

The problem is the compiler has no may of knowing that the A and the Action are compatible sub-classes of Action

A simple work around is to not be so specific. Use Action instead of A in this method.

public List<Action> getActionsFor(Actor a) {
    // this has to return a copy of the List or you will be modifying an original
    List<Action> theActions = super.getActionsFor(a);

    for (Action ac: a.getItemCarried().getActions()) {
        theActions.add(ac); // ac is an Action so all good.
    }

    return theActions;
}

OR you could do what you had, but more complicated

public <A extends Action> List<A> getActionsFor(Actor<A> a) {
    List<A> theActions = super.getActionsFor(a);

    for (A ac: a.getItemCarried().getActions()) {
        theActions.add(ac); // ac is an A, so all good.
    }

    return theActions;
}

Altri suggerimenti

You are declaring an explicit list of A, if you want to accept all subclasses, specify so in your list declaration:

List<? extends A> theActions = super.getActionsFor(a);

If you are using <A extends Action> as generic type you cannot add elements to a List typed with A in a typesafe way.

The reason for this is that you don't know the exact type of A.

Lets assume you have two subclasses of Action: ActionA and ActionB.

Now it is perfectly valid to write this:

List<A> theActions = new ArrayList<ActionA>();

But now you can't add any object to theActions because the type of theActions (<A extends Action>) does not tell you if it is a List of Action, ActionA or ActionB. Therefore you can't add anything to theActions:

theActions.add(new Action()); // doesn't compile

In your example you have not specified what is the A that is a subclass of Action. You want to add an instance of a supertype of A (an Action), that is not allowed. You need to cast to A (not safe, gives warning), or return just List<Action>.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top