Come discusso nei commenti, il vostro disegno richiede che il metodo getCopy
restituire il "tipo di auto" - cioè, un'implementazione BlueStack<T>
ci si aspetterebbe per restituire un BlueStack<T>
dalla sua getCopy
, e RedStack<T>
dovrebbe restituire un RedStack<T>
ecc
Sfortunatamente, non c'è modo di esprimere il "self-type" in Java. Come zhong.j.yu points out, un parametro di tipo ricorsivo si avvicina, per esempio:
//not recommended!
public interface Stack<S extends Stack<S, T>, T extends Item> {
S getCopy();
}
Ma come zhong.j.yu menzioni questo è poco intuitivo e sarebbe ancora non riescono a impedire che un BlueStack<T>
da "mentire" e di ritorno a RedStack<T>
dal suo getCopy
.
Invece, consiglio una riprogettazione. Prova a disaccoppiare la responsabilità di copiare pile dal tipo Stack
. Per esempio:
public interface StackCopier<S extends Stack<T>, T extends Item> {
S copy(S original);
}
Se implementazioni di StackCopier
bisogno di accedere ai membri privati delle rispettive Stack
s, si consideri che li rende classi nidificate, ad esempio:
class BlueStack<T extends Item> implements Stack<T> {
...
static class Copier<T extends Item> implements StackCopier<BlueStack<T>, T> {
@Override
public BlueStack<T> copy(BlueStack<T> original) {
...
}
}
Naturalmente SimpleFinder
avrebbe bisogno di essere cambiato in o avere un campo StackCopier<S, T>
o prendere uno come un nuovo parametro di find
:
private final StackCopier<S, T> copier = ...;
public S find(S stack, int a) {
S stackCopy = copier.copy(stack);
...
return stackCopy;
}
La migliore linea d'azione per ottenere cosa? Perché non riesci a modificare le definizioni delle interfacce? – Bobulous
prova il cast bruto. ci sono modi per risolverlo (parametro di tipo ricorsivo) ma non ne vale la pena. – ZhongYu
@Arkanon perché non è il mio a cambiare ...: | e il cast brutale è piuttosto brutto, vero? – SadStudent