Я пытаюсь создать класс, который может содержать только один из двух объектов, и я хочу сделать это с помощью дженериков. Вот идея:
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...
}
Конечно, это не сработает, потому что из-за стирания типа конструкторы имеют одну и ту же подпись типа. Я понимаю, что одно решение состоит в том, чтобы иметь один конструктор, беря оба, но я хочу, чтобы одно из значений было пустым, поэтому кажется более элегантным иметь конструкторы с одним параметром.
// 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;
}
Есть ли элегантное решение для этого?
Изменить 1: Я использую Java 6.
Изменить 2: Причина, по которой я хочу это сделать, заключается в том, что у меня есть метод, который может возвращать один из двух типов. Я сделал конкретную версию без каких-либо дженериков, но задавался вопросом, могу ли я сделать ее обобщенной. Да, я понимаю, что наличие метода с двумя разными типами возвращаемых данных является реальной проблемой, но мне все еще было любопытно, был ли хороший способ сделать это.
Я думаю, durron597 answer лучше всего, потому что он указывает, что
Union<Foo, Bar>
иUnion<Bar, Foo>
должны действовать одинаково, но они этого не делают (что является основной причиной почему я решил прекратить это делать). Это гораздо более уродливая проблема, чем "уродливый" конструктор.Для чего я думаю, что лучший вариант, вероятно, делает этот абстрактный (потому что интерфейсы не могут диктовать видимость) и создавать
isA
иgetA
материалprotected
, а затем в классе реализации лучше назвать методы, чтобы избежать проблемы<A, B>
!=<B, A>
. Я добавлю свой собственный ответ более подробно.
Заключительное редактирование:. Для чего я решил, что использование статических методов в качестве псевдоконструкторов (
public static Union<A, B> fromA(A a)
иpublic static Union<A, B> fromB(B b)
) - лучший подход (вместе с тем, что частный конструктор является частным).Union<A, B>
иUnion<B, A>
никогда не сравнивались бы реалистично друг с другом, когда он использовался только как возвращаемое значение.
Другое редактирование, 6 месяцев вне. Я действительно не могу поверить, насколько наивным был я, когда я спрашивал об этом, статические методы factory настолько очевидны, что это абсолютно правильный выбор и, очевидно,.
Все, что в стороне, я нашел Functional Java очень интригующим. Я еще не использовал его, но я нашел этот
Either
, когда googling 'java disjunct union', это именно то, что я искал, Недостатком является то, что функциональная Java предназначена только для Java 7 и 8, но, к счастью, проект теперь я работаю над используемой Java 8.