Sto provando a creare una classe che possa contenere solo uno di due oggetti e voglio farlo con i generici. Ecco l'idea:Gestione del tipo di cancellazione nei costruttori con generici
public class Union<A, B> {
private final A a;
private final B b;
public Union(A a) {
this.a = a;
b = null;
}
public Union(B b) {
a = null;
this.b = b;
}
// isA, isB, getA, getB...
}
Naturalmente questo non funziona, però, perché a causa della cancellazione di tipo costruttori hanno la stessa firma tipo. Mi rendo conto che una soluzione è di avere un singolo costruttore che prenda entrambi, ma voglio che uno dei valori sia vuoto, quindi sembra più elegante avere costruttori a parametro singolo.
// Ugly solution
public Union(A a, B b) {
if (!(a == null^b == null)) {
throw new IllegalArgumentException("One must exist, one must be null!");
}
this.a = a;
this.b = b;
}
C'è una soluzione elegante a questo?
Edit 1: Sto usando Java 6.
Edit 2: Il motivo che voglio fare questo è perché ho un metodo che può restituire uno di due tipi. Ho fatto una versione concreta senza farmaci generici, ma mi chiedevo se potevo renderla generica. Sì, mi rendo conto che avere un metodo con due diversi tipi di ritorno è il vero problema, ma ero comunque curioso di sapere se c'era un buon modo per farlo.
penso durron597's answer è migliore, perché sottolinea che
Union<Foo, Bar>
eUnion<Bar, Foo>
dovrebbe agire lo stesso ma non lo fanno (che è il motivo principale per cui ho deciso di smettere di perseguire questo). Questo è un problema molto più brutto rispetto al costruttore "brutto".Per quello che vale Credo che l'opzione migliore è probabilmente rendere questo abstract (perché le interfacce non possono dettare la visibilità) e rendere il
isA
egetA
robaprotected
, e poi nella classe che implementa avere metodi più chiamati per evitare il<A, B>
! =<B, A>
problema. Aggiungerò la mia risposta con maggiori dettagli.
montaggio finale: Per quel che vale, ho deciso che l'utilizzo di metodi statici, come costruttori di pseudo (
public static Union<A, B> fromA(A a)
epublic static Union<A, B> fromB(B b)
) è l'approccio migliore (insieme a fare il costruttore vero e privato).Union<A, B>
eUnion<B, A>
non sarebbero mai realisticamente confrontati l'uno con l'altro quando è solo utilizzato come valore di ritorno.
Un'altra modifica, 6 mesi fuori: Davvero non riesco a credere quanto ingenuo ero quando ho chiesto questo, metodi factory statici sono così ovviamente la corretta scelta assoluta e chiaramente un gioco da ragazzi .
Tutto questo a parte ho trovato Functional Java molto intrigante. Non l'ho ancora usato, ma ho trovato questo
Either
quando ho cercato su Google 'java disjunct union', è esattamente quello che stavo cercando. Lo svantaggio è che Java funzionale è solo per Java 7 e 8, ma fortunatamente il progetto su cui sto lavorando ora utilizza Java 8.
È possibile nascondere il costruttore della "brutta soluzione" dietro i metodi di fabbrica. – khelwood
dovresti usare l'interfaccia qui – HuStmpHrrr
Le fabbriche statiche sono la strada da percorrere in generale. Anche se hai due campi che si escludono a vicenda, è sempre sospetto. – biziclop