2014-10-04 2 views
2

В Java я могу сказать class SomeClass<T extends Thing>. Но есть ли способ сказать, что я хочу T продлить либо Thing, либо SomethingElse?Есть ли способ в Java Generics сказать, что «T extends Thing или T extends SomethingElse»?

+2

Нет, нет. Представьте, что вы компилятор. Как бы вы набрали чек, когда вы вызываете метод, который не находится в обеих Thing и SomethingElse. Можете ли вы добавить интерфейс с помощью методов, которые вам нужны, или вы можете разлить свой метод/класс. –

+0

Нет, нет. Дженерики должны объединяться. – user2864740

+2

И как бы ' 'work, если я сделал' final X x = getx() 'и пытался вызвать методы на' x'? –

ответ

1

Невозможно сделать это в Java, как было предложено - Java не поддерживается algebraic data types.

ограничения Generic типа Java должны унифицировать к одному типу так же, как выражения в Java должны объединить к одному типу - например. он является недействительным по той же причине, как пытаться использовать :

{ArrayList | HashSet} collection = ..; 

Однако, так как они оба этих типа унифицировать в коллекции, то справедливо следующее:

Collection collection = createArrayListOrHashSetAndReturnACollection(); 

Теперь, в зависимости по необходимости есть два общих способа, в которых задача может обрабатываться, возвращаясь к вышеуказанным ограничениям:

  1. Типы, о которых идет речь, могут распространяться (или лучше наследовать) из общего типа и могут затем объединить вокруг этого типа. Это может включать модификацию рассматриваемых типов по мере необходимости.

  2. Может быть создан другой тип (поддерживаемый интерфейсом, возможно, с использованием композиции), который действует как прокси для типов Thing/SomethingElse. Общее ограничение теперь объединяет в этом новом типе/интерфейсе.

  3. Удалить ограничение типа и унифицировать вокруг объекта; это наименее утонченная унификация каждого не примитивного типа в Java.


Хотя это не является ограничением «ООП», дженериков/шаблонов или статических типов-систем в целом, это является как Java работает: Неа, не может сделать что.

-4

Нет, нет. На каждом объектно-ориентированном языке класс может распространяться только на один класс.

Вместо этого, вы можете использовать что-то вроде:
MyClassOne расширяет то
MyClassTwo расширяет SomethingElse

если (...)
MyClassOne
еще
MyClassTwo

+4

Не говорите «каждый» язык так небрежно, так как ответ «не так» * при этом. Кроме того, языки ООП * могут * поддерживать не номинативные типы. Теперь вопрос * есть * о Java и использует правильный (не «каждый») контекст * can * и должен использоваться для определения поведения в конкретном контексте. – user2864740

+0

@ user2864740 Не будьте так жестоки с ним. Люди ошибаются. –

+1

@AvivCohn Я не считаю это настолько суровым (после моих ревизий); и я даже не проголосовал. Скорее это объясняет одну из основных проблем с ответом, как исправить это, почему это было беспощадно проголосовано. – user2864740

-1

You мог сделать это следующим образом

public abstract class SomeClass<T>{ 

} 

public class StringSomeClass : SomeClass<String>{ 

} 

public class IntegerSomeClass : SomeClass<Integer>{ 

} 
1

на самом деле существует очень хорошо известное кодирование алгебраических типов данных в Java. Он называется шаблоном посетителя. И есть даже временное решение для компиляции, чтобы упростить реализацию этого шаблона: см. Проект adt4j в Github.

Но то, что вы ищете, это Generalized algebraic data type (GADT).

Оказывается, что Java также поддерживает GADT (и без литья типов). См. Этот пример как пример изящного решения проблемы выражения с помощью GADT: https://gist.github.com/jbgi/208a1733f15cdcf78eb5 - В этом коде мы определяем класс Term, где T статически ограничено как Integer, так и Boolean.

Смежные вопросы