Cela signifie que l'argument de type pour enum doit dériver d'un enum qui a lui-même le même argument de type. Comment cela peut-il arriver? En faisant de l'argument de type le nouveau type lui-même. Donc, si j'ai une énumération appelée StatusCode, ce serait équivalent à:
public class StatusCode extends Enum<StatusCode>
Maintenant, si vous vérifiez les contraintes, nous avons Enum<StatusCode>
- donc E=StatusCode
. Vérifions: E
s'étend-il Enum<StatusCode>
? Oui! Nous allons bien.
Vous vous demandez peut-être à quoi cela sert :) Eh bien, cela signifie que l'API pour Enum peut se référer à elle-même - par exemple, être capable de dire qu'elle Enum<E>
implémente Comparable<E>
. La classe de base est capable de faire les comparaisons (dans le cas des énumérations) mais elle peut s'assurer qu'elle compare uniquement le bon type d'énumérations entre elles. (EDIT: Eh bien, presque - voir la modification en bas.)
J'ai utilisé quelque chose de similaire dans mon port C # de ProtocolBuffers. Il existe des «messages» (immuables) et des «générateurs» (mutables, utilisés pour construire un message) - et ils se présentent sous la forme de paires de types. Les interfaces concernées sont:
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>
Cela signifie qu'à partir d'un message, vous pouvez obtenir un constructeur approprié (par exemple pour prendre une copie d'un message et modifier certains bits) et d'un constructeur, vous pouvez obtenir un message approprié lorsque vous avez fini de le construire. C'est un bon travail que les utilisateurs de l'API n'ont pas besoin de se soucier de cela - c'est horriblement compliqué et il a fallu plusieurs itérations pour en arriver là.
EDIT: Notez que cela ne vous empêche pas de créer des types impairs qui utilisent un argument de type qui lui-même est correct, mais qui n'est pas du même type. Le but est de donner des avantages dans le bon cas plutôt que de vous protéger du mauvais cas.
Donc, si Enum
vous n'avez pas été manipulé "spécialement" en Java de toute façon, vous pouvez (comme indiqué dans les commentaires) créer les types suivants:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
Second
mettrait en œuvre Comparable<First>
plutôt que Comparable<Second>
... mais First
lui-même serait très bien.