Ich versuche, eine Klasse zu machen, die nur eines von zwei Objekten enthalten kann, und ich möchte dies mit Generika tun. Hier ist die Idee:Behandlungstyp Löschen in Konstruktoren mit Generika
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...
}
Natürlich wird dies allerdings nicht, da arbeiten aufgrund Typ Löschung die Konstrukteure haben die gleiche Art Signatur. Ich stelle fest, dass eine Lösung darin besteht, einen einzelnen Konstruktor zu haben, der beides akzeptiert, aber ich möchte, dass einer der Werte leer ist, daher scheint es eleganter zu sein, Einzelparameterkonstruktoren zu haben.
// 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;
}
Gibt es eine elegante Lösung?
Edit 1: Ich bin mit Java 6.
Edit 2: Der Grund, warum ich dies machen wollen, weil ich eine Methode, die kann einen von zwei Typen zurückgeben. Ich machte eine konkrete Version ohne Generika, aber ich fragte mich, ob ich es generisch machen könnte. Ja, mir ist klar, dass eine Methode mit zwei verschiedenen Rückgabetypen das eigentliche Problem ist, aber ich war immer noch neugierig, ob es einen guten Weg dafür gibt.
Ich denke durron597's answer am besten ist, weil es darauf hinweist, dass
Union<Foo, Bar>
undUnion<Bar, Foo>
sollten die gleichen handeln, aber sie nicht (das ist der Hauptgrund, warum ich dies zu stoppen entschieden verfolgt). Das ist ein viel hässlicheres Problem als der "hässliche" Konstruktor.Für das, was es wert ist, ich denke, die beste Option ist wahrscheinlich diese abstrakte machen (weil Schnittstellen nicht Sichtbarkeit diktieren kann) und machen die
isA
undgetA
Sachenprotected
, und dann in der implementierenden Klasse haben eine bessere genannten Methoden die vermeiden<A, B>
! =<B, A>
Problem. Ich werde meine eigene Antwort mit mehr Details hinzufügen.
Finale edit: Für das, was es wert ist, habe ich beschlossen, dass die Verwendung von statischen Methoden als Pseudo-Konstrukteure (
public static Union<A, B> fromA(A a)
undpublic static Union<A, B> fromB(B b)
) ist der beste Ansatz (zusammen mit der realen Konstruktor privat machen).Union<A, B>
undUnion<B, A>
würde nie realistisch miteinander verglichen werden, wenn es nur als Rückgabewert verwendet wird.
Ein anderes bearbeitet, 6 Monate out: Ich kann wirklich nicht glauben, wie naiv ich war, als ich diese gefragt, sind statische Factory-Methoden so offensichtlich die absolute richtige Wahl und eindeutig ein Kinderspiel .
All das beiseite habe ich Functional Java gefunden, um sehr faszinierend zu sein. Ich habe es noch nicht benutzt, aber ich fand das
Either
beim googeln von 'java disjunct union', es ist genau das, wonach ich gesucht habe. Der Nachteil ist, dass Functional Java nur für Java 7 und 8 gedacht ist, aber glücklicherweise verwendete das Projekt, an dem ich gerade arbeite, Java 8.
Sie können Ihren "hässlichen Lösung" -Konstruktor hinter Fabrikmethoden verstecken. – khelwood
sollten Sie hier die Schnittstelle verwenden – HuStmpHrrr
Statische Fabriken sind der Weg zu gehen im Allgemeinen. Wenn Sie jedoch zwei Felder haben, die sich gegenseitig ausschließen, ist das immer verdächtig. – biziclop