Je me suis réfléchi pendant un moment pourquoi Java et C # (et je suis sûr d'autres langues) par défaut pour faire référence à l'égalité pour ==
.
Dans la programmation, je le fais (ce qui n'est certainement qu'un petit sous-ensemble de problèmes de programmation), je veux presque toujours une égalité logique lors de la comparaison des objets au lieu de l'égalité de référence. J'essayais de penser à la raison pour laquelle ces deux langues passaient cette voie au lieu de l'inversion et d'avoir ==
Soyez une égalité logique et en utilisant .ReferenceEquals()
pour l'égalité de référence.
De toute évidence, utiliser l'égalité de référence est très simple à mettre en œuvre et donne un comportement très cohérent, mais il ne semble pas que cela convient parfaitement à la plupart des pratiques de programmation que je vois aujourd'hui.
Je ne souhaite pas sembler ignorer les problèmes qui tentent de mettre en œuvre une comparaison logique et qu'il doit être mis en œuvre dans chaque classe. Je me rends également compte que ces langues ont été conçues il y a longtemps, mais la question générale est debout.
Y a-t-il un avantage majeur de la défaillance de celle-ci que je suis tout simplement manquante, ou semble-t-il raisonnable que le comportement par défaut soit une égalité logique et de remettre en défaut à l'égalité de référence une égalité logique n'existe pas pour la classe?
C # est-ce parce que Java a fait. Java a fait parce que Java ne prend pas en charge la surcharge de l'opérateur. Puisque l'égalité de la valeur doit être redéfinie. Pour chaque classe, il ne pouvait pas être un opérateur, mais devait plutôt être une méthode. IMO c'était une mauvaise décision. Il est beaucoup plus facile de écrire à la fois écrire et lire a == b
que a.equals(b)
, et beaucoup plus naturel pour les programmeurs avec une expérience C ou C++, mais a == b
est presque toujours faux. Bugs à partir de l'utilisation de ==
Où .equals
ont été gaspillés des milliers d'heures de programmeur .
La réponse courte: cohérence
Pour répondre correctement à votre question, je suggère que nous prenions un pas en arrière et que nous examinons la question de ce que l'égalité signifie dans un langage de programmation. Il y a au moins [~ # ~ ~] trois [~ # ~ ~] Différentes possibilités, utilisées dans différentes langues:
Ces trois types d'égalité sont souvent utilisés car ils sont pratiques pour mettre en œuvre: les trois contrôles d'égalité peuvent facilement être générés par un compilateur (dans le cas d'égalité profonde, le compilateur peut avoir besoin d'utiliser des bits d'étiquette pour empêcher les boucles infinies si une structure à être comparé a des références circulaires). Mais il y a un autre problème: aucun de ceux-ci ne pourrait être approprié.
Dans des systèmes non triviaux, l'égalité des objets est souvent définie comme une quelque chose entre l'égalité profonde et référence. Pour vérifier si nous voulons considérer deux objets comme étant égaux dans un certain contexte, nous pourrions avoir besoin de certains attributs à comparer là où il se situe dans la mémoire et d'autres par une égalité profonde, tandis que certains attributs peuvent être autorisés à être quelque chose de différent. Ce que nous aimerions vraiment, c'est un "type d'égalité", un très gentil, souvent appelé dans la littérature égalité sémantique. Les choses sont égales si elles sont égales dans notre domaine. =)
Nous pouvons donc revenir à votre question:
Y a-t-il un avantage majeur de défaut à cela que je suis tout simplement manquant ou semble-t-il raisonnable que le comportement par défaut soit une égalité logique et de remettre en défaut sur l'égalité de référence si une égalité logique n'existe pas pour la classe?
Que voulons-nous dire quand nous écrivons 'A == B' dans n'importe quelle langue? Idéalement, il devrait toujours être la même chose: l'égalité sémantique. mais ce n'est pas possible.
L'une des principales considérations est que, du moins pour des types simples comme des chiffres, nous nous attendons à ce que deux variables soient égales après l'affectation de la même valeur. Voir ci-dessous:
var a = 1;
var b = a;
if (a == b){
...
}
a = 3;
b = 3;
if (a == b) {
...
}
Dans ce cas, nous nous attendons à ce que "un égal b" dans les deux déclarations. Tout le reste serait fou. La plupart (sinon toutes) des langues suivent la présente convention. Par conséquent, avec des types simples (valeurs AKA), nous savons comment atteindre l'égalité sémantique. Avec des objets, cela peut être quelque chose de complètement différent. Voir ci-dessous:
var a = new Something(1);
var b = a;
if (a == b){
...
}
b = new Something(1);
a.DoSomething();
b.DoSomething();
if (a == b) {
...
}
Nous nous attendons à ce que le premier "si" soit toujours vrai. Mais qu'attendez-vous sur la deuxième "si"? Cela dépend vraiment. Peut-on changer "DOSOMMANTIQUE" l'égalité (sémantique) d'A et B?
Le problème avec l'égalité sémantique est qu'il ne peut pas être généré automatiquement par le compilateur pour des objets, ni évident des missions. Un mécanisme doit être fourni à l'utilisateur de définir l'égalité sémantique. Dans les langues orientées objet, ce mécanisme est une méthode héritée: égale. Lecture d'un morceau de OO code, nous ne nous attendons pas à ce qu'une méthode ait la même mise en œuvre exacte dans toutes les classes. Nous sommes habitués à héritage et à surcharge.
Avec des opérateurs, cependant, nous nous attendons au même comportement. Lorsque vous voyez 'A == B', vous devez vous attendre au même type d'égalité (à partir de 4 ci-dessus) dans toutes les situations. Ainsi, visant cohérence Les concepteurs de langues utilisaient l'égalité de référence pour tous types. Il ne doit pas dépendre de la question de savoir si un programmeur a remplacé une méthode ou non.
PS: la langue de la langue est légèrement différente de Java et C #: l'opérateur égal signifie l'égalité peu profonde pour les types simples et l'égalité sémantique pour les classes définies par l'utilisateur (avec la responsabilité de la mise en œuvre de l'opération. L'utilisateur - aucune valeur par défaut n'est fourni). Comme pour les types simples, l'égalité peu profonde est toujours une égalité sémantique, la langue est cohérente. Le prix qu'il paye, cependant, est que l'opérateur égal est par défaut non défini pour l'utilisateur. types définis. Vous devez la mettre en œuvre. Et parfois, c'est juste ennuyeux.
J'essayais de penser à la raison pour laquelle ces deux langues passaient cette voie au lieu de l'inversion et d'avoir == être une égalité logique et d'utiliser .Refentequensibles () pour l'égalité de référence.
Parce que cette dernière approche serait déroutante. Envisager:
if (null.ReferenceEquals(null)) System.out.println("ok");
Si ce code Imprimer "ok"
, ou devrait-il lancer un NullPointerException
?