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