Comment remplacer le (final) est égal à la méthode en java énumérations?
J'ai un problème avec la substitution de la méthode equals dans un Enum pour le rendre compatible avec d'autres classes.
L'Enum implémente une interface, et l'idée est que toutes les implémentations de cette interface peuvent être testés pour l'égalité, indépendamment de leur type. Par Exemple:
public interface Group {
public Point[] getCoordinates();
}
public enum BasicGroups implements Group {
a,b,c; //simplified, they actually have constructors
//+ fields and methods
}
public class OtherGroup implements Group {
//fields and methods
}
Si un BasicGroup
et un OtherGroup
ont les mêmes coordonnées (dans un ordre arbitraire), puis la méthode equals doit retourner true.
Pas de problème lors de l'exécution de myOtherGroup.equals(BasicGroup.a)
mais depuis la méthode equals dans les Énumérations est définitive, je ne peux pas les remplacer.
Est-il un moyen de contourner cela? Comme lors de l'essai sur un autre BasicGroup la valeur par défaut est égale à la méthode (référence à l'égalité) est utilisé et lors de l'essai d'autres classes de mon propre mise en œuvre est utilisée. Et comment puis-je vérifier que java n'utilise pas le mal quand je ne BasicGroup.a.equals(myOtherGroup)
?
- Comme @aioobe dit: ce n'est point pour remplacer méthode equals pour un enum. Il n'y aura que les énumérations que vous avez fourni (vous ne pouvez pas créer de nouvelles instances de code client) et un seul sera égal à a, b to b, et ainsi de suite...
- +1, très bonne question. EJ2 dit que nous pouvons imiter extensible
enum
avecinterface
, mais si c'interface
spécifie commentequals
doit se comporter pour des réalisateurs (alaList
), alors vous ne pouvez pas utiliserenum
à mettre en œuvre. Quelle poisse. - Le point est d'être compatible avec d'autres classes. Contrat général de la méthode equals déclare qu'il devrait être symétrique. Donc, si j'ai une instance d'une autre classe que je considère comme égal à l'enum, et donc dont la méthode equals renvoie la valeur true, la méthode equals dans mon enum doit retourner true par rapport à d'autres exemple.
- Je dois vraiment avoir de la EJ2. Lorsque Efficace Java (1) a été écrit, les Énumérations n'existait pas encore.
- Vous m'a fait réfléchir. Dans la première édition, Josué donne des précisions sur l'enum modèle avant de les enums existe en java. Pourrait être une solution à mon problème! merci!
Vous devez vous connecter pour publier un commentaire.
Vous pouvez PAS
@Override
unfinal
méthode (§8.4.3.3); c'est beaucoup plus clair.enum
types (§8.9) sont traités spécialement en Java, ce qui est pourquoi lesequals
estfinal
(égalementclone
,hashCode
, etc.) Il est tout simplement pas possible de@Override
laequals
méthode d'unenum
, ni vous voulez vraiment dans une plus typique scénario d'utilisation.CEPENDANT, regarder la grande image, il semble que vous essayez de suivre le modèle recommandé dans Efficace Java 2nd Edition, Point 34: Émuler extensible enums, avec des interfaces (voir la guide de langue pour plus d'informations sur
enum
):Vous avez défini ce
interface
(maintenant documenté explicitement prévuequals
comportement):Il est parfaitement acceptable pour un
interface
pour définir commentequals
méthode pour des réalisateurs devraient se comporter, bien sûr. C'est exactement le cas avec, par exemple,Liste.égal à
. Un videLinkedList
estequals
à un videArrayList
et vice versa, parce que c'est ce que l'interface
mandats.Dans votre cas, vous avez choisi de mettre en œuvre certaines
Group
commeenum
. Malheureusement, maintenant, vous ne pouvez pas mettre en œuvreequals
conformément à la spécification, puisque c'estfinal
et vous ne pouvez pas@Override
il. Toutefois, étant donné que l'objectif est de se conformer à laGroup
type, vous pouvez utiliser décorateur modèle en ayant unForwardingGroup
comme suit:Maintenant, au lieu d'utiliser votre
enum
constantes directement commeGroup
, vous envelopper dans une instance d'unForwardingGroup
. Maintenant, ceGroup
objet souhaitéequals
comportement, comme spécifié par lainterface
.Qui est, au lieu de:
Vous avez maintenant quelque chose comme:
Notes complémentaires
Le fait que
enum BasicGroups implements Group
, même s'il n'a pas lui-même de suivre le cahier des charges deGroup.equals
, devrait être très clairement documentées. Les utilisateurs doivent être avertis que les constantes doivent être enveloppé par exemple à l'intérieur d'unForwardingGroup
pour une bonneequals
comportement.Notez également que vous pouvez mettre en cache les instances de
ForwardingGroup
, un pour chaqueenum
constantes. Cela permettra de réduire le nombre d'objets créés. Comme par Efficace Java 2nd Edition, Article 1: Envisager statique usine méthodes à la place des constructeurs, vous pouvez envisager d'avoirForwardingGroup
définir unstatic getInstance(Group g)
méthode à la place du constructeur, de laisser revenir les instances mises en cache.Je suis en supposant que
Group
est immuable type (Efficace Java 2nd Edition, Point 15: Minimiser la mutabilité), ou alors vous ne devriez probablement pas la mettre en œuvre avecenum
en premier lieu. Étant donné que, d'envisager Efficace Java 2nd Edition, Article 25: Préférez les listes de tableaux. Vous pouvez choisir d'avoirgetCoordinates()
retour d'unList<Point>
au lieu dePoint[]
. Vous pouvez utiliserCollections.unmodifiableList
(un autre décorateur!), qui fera le retourList
immuable. En revanche, comme les tableaux sont mutables, vous seriez forcés de jouer défensif de la copie lors du retour d'unePoint[]
.Voir aussi
com.google.commun.collecter.ForwardingObject
hashCode
lorsque vous remplacezequals
.Group
devrait préciser quelles sont seshashCode
devrait revenir (tout commeList.hashCode
). Une autre idée: utiliser un adaptateur à la place de la décoratrice. Essentiellement votreenum
lui-même n'a pasimplements Group
(puisqu'il ne peut pas vraiment le faire sans violer lesequals/hashCode
contrat). Donc, au lieu de cela, chaque constante est une référence à unGroup
wrapper qui ne leequals/hashCode
pour elle.Group g = BasicGroup.A;
(où vous ne pouvez pas le faire depuisBasicGroup
plusimplements Group
, vous neGroup g = BasicCoordinates.A.asGroup()
, où la méthode renvoie une référence à unfinal Group wrapper
champ. De cette façon, vous n'avez pas à vous soucier de la gestion cache des instances de décorateurs, puisque chaque constante est son propre emballage. Je peux en dire plus sur ce concept plus en détail si nécessaire.Il n'est pas possible de le faire en Java. (Le seul but de la finale de mot-clé quand il s'agit de méthodes, est de prévenir primordial!)
equals
et quelques autres méthodes sur les Énumérations sont finale, de sorte que vous ne pouvez pas modifier le comportement d'entre eux. (Et vous ne devrait pas 🙂 Voici ma réponse à une une question relative à la:L'intuition de clients qui traitent avec le protocole enum constantes est que les deux constantes sont
equal
si et seulement si elles sont la même constante. Ainsi, tous les autres de la mise en œuvre dereturn this == other
serait contraire à l'intuition et sujettes à erreur.Même raisonnement s'applique à
hashCode()
,clone()
,compareTo(Object)
,name()
,ordinal()
, etgetDeclaringClass()
.La JLS ne pas motiver le choix de faire ce final, mais mentionne égaux dans le contexte d'énumérations ici. Extrait de:
Vous pouvez résoudre ce problème en appelant la méthode hasSameCoordinatesAs, ou similaire, plutôt que d'égal à égal.
est égal pour les enums est définie dans la spécification du langage, de sorte que vous ne peut pas espérer la redéfinir.
L'égalité est tout à fait insaisissable. Différents contextes nécessitent différents la relation d'égalité. En ayant de la méthode equals() sur l'Objet, Java impose une "intrinsèque" de l'égalité, et de l'Api, comme, en dépendent.
Pendant ce temps, la commande n'est pas considéré comme "intrinsèque", deux objets peuvent être organisées différemment dans des contextes différents, et les Api d'habitude, nous permettent d'offrir un comprator, c'est à dire, une coutume de la commande de la relation.
Ce qui est intéressant. En termes mathématiques, de l'égalité, comme l'ordre, c'est juste une relation, et il peut être différent de la relation d'égalité. Le concept de "l'égalité intrinsèque" n'est pas saint.
donc nous allons avoir un pied d'Égalité-ator trop, et le changement des Api pour accepter personnalisée de la relation d'égalité:
En fait, nous pouvons construire des wrappers autour de l'actuelle collection d'Api, et l'ajout de cette fonctionnalité de nouvelle égalité.
Cela peut répondre à votre question. Pourquoi avez-vous une dépendance sur equals() en premier lieu? Et pouvez-vous supprimer, et dépendent plutôt de "equalator"? Alors vous êtes fixés.