En Ruby, quelle est la différence entre == et ===? Le RDoc dit
Egalité de cas – Pour Object de classe, le même que pour appeler # ==, mais généralement remplacé par des descendants pour fournir une sémantique significative dans les instructions de cas.
Est-ce que #==
le même que ==
? Et pourriez-vous donner un exemple de quand / comment cela est utilisé dans les déclarations de cas?
Les deux n’ont vraiment rien à voir les uns avec les autres. En particulier, #==
est l’opérateur d’égalité et #===
n’a absolument rien à voir avec l’égalité. Personnellement, je trouve plutôt regrettable que #===
ressemble tellement à #==
, utilise le signe égal et est souvent appelé l’ opérateur d’égalité de casse, l’opérateur sortingple equals ou l’ opérateur sortingple lorsqu’il n’a rien à voir avec l’égalité.
J’appelle #===
l’ opérateur de la subsomption de cas (c’est le mieux que je puisse trouver, je suis ouvert aux suggestions, en particulier celles des anglophones natifs).
La meilleure façon de décrire a === b
est “si j’ai un tiroir étiqueté a
, est-il judicieux d’y mettre b
?”
Ainsi, par exemple, le Module#===
teste si b.is_a?(a)
. Si vous avez un Integer === 2
, est-il judicieux de mettre 2
dans une case intitulée Integer
? Oui. Qu’en est-il Integer === 'hello'
? Évidemment pas.
Un autre exemple est Regexp#===
. Il teste un match. Est-il judicieux de mettre 'hello'
dans une case intitulée /el+/
? Oui.
Pour les collections telles que les plages, la Range#===
est définie comme un test d’appartenance: il est logique de placer un élément dans une zone étiquetée avec une collection si cet élément est dans la collection.
Donc, c’est ce que fait #===
: il teste si l’argument peut être inclus dans le récepteur.
Qu’est-ce que cela doit avec les expressions de case
? Simple:
case foo when bar baz end
est le même que
if bar === foo baz end
Oui, par #==
les documents signifient “la méthode d’instance ==
de l’object actuel”.
===
est utilisé dans les déclarations de cas en tant que telles:
case obj when x foo when y bar end
Est le même que
if x === obj foo elsif y === obj bar end
Certaines classes qui définissent leurs propres ===
sont Range (pour agir comme include?
), Class (pour agir comme obj.is_a?(klass)
) et Regexp
(pour agir comme =~
sauf pour renvoyer un booléen). Certaines classes qui ne définissent pas leurs propres ===
sont les classes numériques et Ssortingng.
Alors
case x when 0 puts "Lots" when Numeric puts(100.0 / x) when /^\d+$/ puts(100.0 / x.to_f) default raise ArgumentError, "x is not a number or numeric ssortingng" end
est le même que
if 0 == x puts "Lots" elsif x.is_a? Numeric puts(100.0 / x) elsif x =~ /^\d+$/ puts(100.0 / x.to_f) else raise ArgumentError, "x is not a number or numeric ssortingng" end
Fait amusant, ===
est également utilisé pour faire correspondre les exceptions dans rescue
Voici un exemple
class Example def self.===(exception) puts "Triple equals has been called." true end end raise rescue Example # => prints "Triple equals has been called." # => no exception raised
Ceci est utilisé pour correspondre aux erreurs du système.
SystemCallError.===
a été défini pour retourner true lorsque les deux ont le même numéro d’erreur. Avec ce système, les erreurs d’appels avec le même numéro d’erreur, telles que Errno::EAGAIN
et Errno::EWOULDBLOCK
, peuvent toutes deux être Errno::EWOULDBLOCK
listant qu’une.