587 votes

Quelle est la différence entre l'égalité?, eql?, = = = et ==?

Je suis en train d'essayer de comprendre la différence entre ces quatre méthodes. Je sais par défaut qu' == appelle la méthode equal? qui renvoie vrai si les deux opérandes reportez-vous à exactement le même objet.

=== par défaut des appels == qui demande equal?... bon, donc, si l'ensemble de ces trois méthodes ne sont pas remplacées, alors je suppose ===, == et equal? faire exactement la même chose?

Vient maintenant eql?. Qu'est-ce faire (par défaut)? Faut-il faire un appel à l'opérande de hachage de l'/id?

Pourquoi Ruby ont donc beaucoup de l'égalité des signes? Sont-ils censés diffèrent dans la sémantique?

817voto

jtbandes Points 39804

Je vais fortement citer l'Objet de la documentation ici, parce que je pense qu'il a quelques grandes explications. Je vous encourage à le lire, et aussi à la documentation de ces méthodes car elles sont remplacées dans d'autres classes, à l'instar de la Chaîne.

Remarque: si vous voulez les essayer pour vous-même sur des objets différents, utiliser quelque chose comme ceci:

class Object
  def all_equals(o)
    ops = [:==, :===, :eql?, :equal?]
    Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
  end
end

"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}

== - générique de "l'égalité"

Au niveau de l'Objet, == renvoie true uniquement si obj et other sont le même objet. En général, cette méthode est redéfinie dans les classes descendantes de fournir spécifiques à la classe de sens.

C'est le plus commun de comparaison, et donc les plus fondamentales de l'endroit où vous (en tant qu'auteur d'une classe) de décider si deux objets sont "égaux" ou pas.

=== - en cas d'égalité

Pour la classe de l'Objet, effectivement la même que l'appel à la #==, mais généralement remplacée par descendants de fournir une sémantique correcte dans le cas des déclarations.

C'est incroyablement utile. Des exemples de choses qui sont intéressantes === implémentations:

  • Gamme
  • Regex
  • Proc (en Ruby 1.9)

Ainsi, vous pouvez faire des choses comme:

case some_object
when /a regex/
  # The regex matches
when 2..4
  # some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
  # the lambda returned true
end

Voir ma réponse ici pour un exemple clair de la façon dont case+Regex peut rendre le code beaucoup plus propre. Et bien sûr, en fournissant votre propre === mise en œuvre, vous pouvez obtenir personnalisé case de la sémantique.

eql? - Hash de l'égalité

L' eql? méthode retourne true si obj et other se réfèrent à la même clé de hachage. Il est utilisé par Hash pour tester les membres de l'égalité. Pour les objets de la classe Object, eql? est synonyme d' ==. Les sous-classes normalement continuer cette tradition en aliasing eql? de leur substituée == méthode, mais il y a des exceptions. Numeric types, par exemple, d'effectuer le type de conversion à travers ==, mais pas à travers des eql?, donc:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

Vous êtes donc libre de remplacer cette valeur pour votre propre usage, ou vous pouvez remplacer == et l'utilisation alias :eql? :== donc, les deux méthodes se comportent de la même manière.

equal? - identité de comparaison

Contrairement aux ==, equal? méthode ne doit jamais être remplacées par des sous-classes: il est utilisé pour déterminer l'identité de l'objet (c'est - a.equal?(b) mfi a est le même objet que l' b).

C'est effectivement le pointeur de la comparaison.

8voto

Kishore Mohan Points 169

=== #---en cas d'égalité

== #--- générique de l'égalité

les deux œuvres similaires, mais "===" même le faire affaire états

"test" == "test"  #=> true
"test" === "test" #=> true

ici la différence

String === "test"   #=> true
String == "test"  #=> false

-9voto

Tom Phan Points 72

J'ai écrit un test simple pour tous les ci-dessus.

def eq(a, b)
  puts "#{[a, '==',  b]} : #{a == b}"
  puts "#{[a, '===', b]} : #{a === b}"
  puts "#{[a, '.eql?', b]} : #{a.eql?(b)}"
  puts "#{[a, '.equal?', b]} : #{a.equal?(b)}"
end

eq("all", "all")
eq(:all, :all)
eq(Object.new, Object.new)
eq(3, 3)
eq(1, 1.0)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X