Isso significa que o argumento de tipo para enum deve derivar de um enum que possui o mesmo argumento de tipo. Como isso pode acontecer? Tornando o argumento de tipo o novo tipo em si. Portanto, se eu tenho uma enumeração chamada StatusCode, seria equivalente a:
public class StatusCode extends Enum<StatusCode>
Agora, se você verificar as restrições, temos Enum<StatusCode>
- então E=StatusCode
. Vamos verificar: se E
estende Enum<StatusCode>
? Sim! Nós estamos bem.
Você pode estar se perguntando qual é o sentido disso :) Bem, isso significa que a API do Enum pode se referir a si mesma - por exemplo, ser capaz de dizer que Enum<E>
implementa Comparable<E>
. A classe base é capaz de fazer as comparações (no caso de enumerações), mas pode garantir que apenas compare o tipo certo de enumeração entre si. (EDIT: Bem, quase - veja a edição na parte inferior.)
Eu usei algo semelhante na minha porta C # do ProtocolBuffers. Existem "mensagens" (imutáveis) e "construtores" (mutáveis, usadas para criar uma mensagem) - e elas vêm como pares de tipos. As interfaces envolvidas são:
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>
Isso significa que, a partir de uma mensagem, você pode obter um construtor apropriado (por exemplo, para tirar uma cópia de uma mensagem e alterar alguns bits) e, a partir de um construtor, você pode receber uma mensagem apropriada quando terminar de construí-la. É um bom trabalho que os usuários da API não precisem realmente se preocupar com isso - é terrivelmente complicado e levou várias iterações para chegar onde está.
Edição: Observe que isso não impede você de criar tipos ímpares que usam um argumento de tipo que por si só é bom, mas que não é do mesmo tipo. O objetivo é oferecer benefícios no caso certo , em vez de protegê-lo do caso errado .
Portanto, se Enum
não fosse tratado "especialmente" em Java, você poderia (como observado nos comentários) criar os seguintes tipos:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
Second
implementaria em Comparable<First>
vez de Comparable<Second>
... mas em First
si seria bom.