Sto riscontrando problemi nell'utilizzo di java generics, in particolare con l'acquisizione di caratteri jolly. Ecco una versione semplificata del codice che ho che mostra il problema che sto vedendo. Mi sta facendo impazzire:Come si risolve questo problema di acquisizione di caratteri jolly quando si utilizzano i java generics?
public class Task {
private Action<ActionResult, ? extends ActionSubject> action;
private ActionSubject subject = new ActionSubjectImpl();
private List<ActionResult> list = new ArrayList<>();
public static void main(String[] args) {
Task task = new Task();
task.setAction(new ActionImpl());
task.doAction();
}
public void setAction(Action<ActionResult, ? extends ActionSubject> action) {
this.action = action;
}
public void doAction() {
list.add(action.act(subject));
}
public static class ActionResult { }
public interface Action<T, U> {
public T act(U argument);
}
public interface ActionSubject {
public String getName();
}
public static class ActionImpl implements Action<ActionResult, ActionSubjectImpl>{
@Override
public ActionResult act(ActionSubjectImpl argument) {
// Code that requires ActionSubjectImpl specifically instead of the interface.
// This classes implmentation of action should only support ActionSubjectImpl as an
// argument.
return new ActionResult();
}
}
public class ActionSubjectImpl implements ActionSubject {
@Override
public String getName() {
return "I am a subject";
}
}
}
La dichiarazione del pacco e le importazioni non sono incluse - altrimenti questo è completo. Questo non viene compilato. Il problema è con il frammento list.add(action.act(subject));
dove sto vedendo il messaggio di errore:
incompatible types: ActionSubject cannot be converted to CAP#1
where CAP#1 is a fresh type-variable:
CAP#1 extends ActionSubject from ? extends ActionSubject
posso vedere da altri posti che metodi di supporto sono suggeriti come un modo ottenere le cose come questo per funzionare, ma non sono stato in grado di ne trovi uno che funzioni.
Il Action action
ha i parametri di tipo in questo modo: Action<ActionResult, ? extends ActionSubject>
e la ActionSubject
che sto passando per il metodo act
è di tipo di interfaccia 'ActionSubject' e di tipo concreto 'ActionSubjectImpl' anche se il frammento di codice in questione non vedrà la tipo concreto naturalmente. Il secondo parametro di tipo Action
dovrebbe supportare qualsiasi tipo che si estende ActionSubject
- e va bene quando si imposta action
su new ActionImpl()
, dove il secondo tipo è ActionSubjectImpl
.
Gradirei qualsiasi commento su ciò che sto facendo male qui nelle mie definizioni e uso di generici. Potrei mancare qualcosa di base qui. Potrei codificarlo in un modo diverso, ma finché non avrò capito cosa sta andando male non potrò andare avanti.
Grazie.
Ciao. Se faccio ciò 'task.setAction (new ActionImpl());' fallisce con 'ActionImpl non può essere convertito in Action' dato che il mio 'ActionImpl' implementa' Action ' –
Forse vuoi il campo deve essere 'private Action action;'? Oppure utilizzare 'Attività ' e renderlo 'Azione privata azione;'? –
MForster
Non saprò in fase di compilazione (all'interno di Task) quale implementazione di Action e quindi quale implementazione di ActionSubject verrà utilizzata, quindi la prima opzione è un no go - ho incluso solo ActionSubjectImpl qui incorporato per dimostrarlo. Ma la seconda opzione è interessante - e funziona per il mio esempio di codice. Lo metterò alla prova con il mio vero codice e se ciò va bene, segnerò questo come risposta. Grazie! –