Generics

Hi,

This is an uneasy question about Generics, so continue if you are very familiar with this concept:

I have a class Action defining an "execute" method:

public abstract class Action<C extends Client> {
    public abstract void execute(LinkedList<String> fields, C client);

This class Action has a whole set of subclasses :

* public class ActionValidateConnection extends Action<EndpointClient> {
      public void execute(LinkedList<String> fields, EndpointClient client);

* public class ActionEcho extends Action<EndpointClientAdmin> {
      public void execute(LinkedList<String> fields, EndpointClientAdmin client);

* etcetera

I use Generics above because the execute method will, as you may see above, either take an EndpointClient interface or an EndpointClientAdmin interface which are both extending Client interface. That's why the class has the following signature: public abstract class Action<C extends Client> { ...

In short, I have a client which recieves messages from the server, and the client is executing the appropriate action according to the message type. I have two types of actions, members actions and admin actions.

Then, I have a dictionary mapping => type of message/Action object :

protected static final Action<EndpointClient> ACTION_SEND_PRIVATE = new ActionSendPrivateMessage();
protected static final Action<EndpointClientAdmin> ACTION_SEND_TO_ALL = new ActionSendMessageToAll();
dictionary.put(Constants.MSG_SEND_PRIVATE, ACTION_SEND_PRIVATE);
dictionary.put(Constants.MSG_SEND_TO_ALL, ACTION_SEND_TO_ALL);

As you may see I want to put Action<EndpointClient> for members messages in the dictionary and Action<EndpointClientAdmin> for admin messages. Per consequent, the dictionary needs to be :
protected static HashMap<String, Action<? extends Client>> dictionary =
    new HashMap<String, Action<? extends Client>>();
And to get an Action from the dictionary :
public Action<? extends Client> getAction(String command) { ... }

Now I have one error in the class which recieves the messages from the server : MessageProcessor
I get the type of message:

public MessageProcessor(String data, EndpointClient client) {
    String[] fields = data.split(Constants.FIELD_DELIMITER);
    String command = fields[0];

Then get the Action from the dictionary:

    Action<? extends Client> action = directory.getAction(command);

And finally execute the Action :

    action.execute(listFields, client);

Error on the line above :

The method execute(LinkedList<String>, capture#3-of ? extends Client) in the type Action<capture#3-of ? extends Client> is not applicable for the arguments (LinkedList<String>, EndpointClient)

I understand the problem that occurs, but I can't find a solution for it. If I change something, error occur other place, etc.
LVL 9
matthew016Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozlevanonCommented:
If I understood the problem correctly (it's a bit hard without full source code), I believe you should explicitly cast the response from the map to ActionValidateConnection , like so:
ActionValidateConnection action = (ActionValidateConnection)directory.getAction(command);

The reason for this is that at this point the action you receive MUST be ActionValidateConnection. If it's not, for example, if it were ActionEcho, you wouldn't have been able to call its execute with "client" whose type is EndpointClient, since the method implementation in ActionEcho doesn't receive EndpointClient, it receives EndpointClientAdmin.

If at this point in your code you KNOW that the value returned from the map is one that can receive an EndpointClient intstance in its action method, then you know more than the code, you know that you actually get an ActionValidateConnection instance, and should cast it accordingly (of course, you can always use instanceof to make sure).
After you cast it to ActionValidateConnection, you should have no problem calling action with "client"

0
mukundha_expertCommented:
your code should look something like this,

the whole problem is Client is not generic, so we would need to wrap it as a generic.

,
your client code now will look like

ClientContainer<EndpointClient> c = null ; //get the instance
            Action<EndpointClient> action = null ;// directory.getAction(command);
          action.execute(new LinkedList<String>(), c);
interface Client{
	
}

abstract class EndpointClientAdmin implements Client{
	
}
abstract class EndpointClient implements Client{
	
}

abstract class ClientContainer<a extends Client>{
	abstract a getClient();
}

abstract class Action<C extends Client> {
    public abstract void execute(LinkedList<String> fields, ClientContainer<C> client);
}

 class ActionValidateConnection extends Action<EndpointClient> {
    public void execute(LinkedList<String> fields, EndpointClient client){
    	
    }

	@Override
	public void execute(LinkedList<String> fields,
			ClientContainer<EndpointClient> client) {
	}
	
}
 
 class ActionEcho extends Action<EndpointClientAdmin> {
    public void execute(LinkedList<String> fields, EndpointClientAdmin client){
    	
    }

	@Override
	public void execute(LinkedList<String> fields,
			ClientContainer<EndpointClientAdmin> client) {
	}
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.