Это означает, что аргумент type для перечисления должен выводиться из перечисления, которое имеет один и тот же аргумент типа. Как это может произойти? Сделав аргумент типа новым типом. Поэтому, если у меня есть перечисление с именем StatusCode, оно будет эквивалентно:
public class StatusCode extends Enum<StatusCode>
Теперь, если вы проверите ограничения, у нас есть Enum<StatusCode>
- так E=StatusCode
. Давайте проверим: расширяет ли E
Enum<StatusCode>
? Да! Мы все в порядке.
Вы вполне можете спросить себя, в чем суть этого :) Ну, это означает, что API для Enum может ссылаться на себя - например, имея возможность сказать, что Enum<E>
реализует Comparable<E>
. Базовый класс способен выполнять сравнения (в случае перечислений), но он может убедиться, что он сравнивает только правильный тип перечислений друг с другом. (EDIT: ну, почти - см. Редактирование внизу.)
Я использовал что-то подобное в моем C # -порте ProtocolBuffers. Существуют «сообщения» (неизменяемые) и «строители» (изменяемые, используемые для создания сообщения), и они являются парами типов. В число задействованных интерфейсов входят:
public interface IBuilder<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
public interface IMessage<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
Это означает, что из сообщения вы можете получить соответствующий строитель (например, взять копию сообщения и изменить некоторые биты), а из строителя вы можете получить соответствующий когда вы закончите его строительство. Это хорошая работа, которую пользователи API не нуждаются в этом, хотя это ужасно сложно, и потребовалось несколько итераций, чтобы добраться туда, где они есть.
EDIT: Обратите внимание, что это не останавливается вы создаете нечетные типы, которые используют аргумент типа, который сам по себе хорошо, но который не является одним и тем же типом. Цель состоит в том, чтобы приносить пользу в случае right , а не защищать вас от неправильного случая .
Так что если Enum
не были обработаны " особенно в Java, вы могли бы (как отмечено в комментариях) создать следующие типы:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
Second
будет реализовывать Comparable<First>
, а не Comparable<Second>
... но First
сам будет хорошо.