Articles

Comment écrire une expression de cas en Ruby

Posted on

Imaginez que vous avez besoin d’un moyen de vérifier la valeur d’un objet, et d’effectuer une action différente en fonction de cela. Le moyen de la programmation orientée objet est d’utiliser le polymorphisme, et nous verrons comment le faire dans une seconde.

Mais d’abord, regardons comment fonctionne l’expression case, et comment vous pouvez l’utiliser pour atteindre le but mentionné ci-dessus.

Comment fonctionne l’expression ?

Il y a deux parties principales à l’expression case. La clause case, et la clause when.

La clause when est l’expression qui définit le récepteur de l’opérateur (par défaut ===), et la clause case définit l’argument qui lui est passé.

Voyons un exemple.

case awhen String #..end

Vous pouvez donc considérer l’exemple ci-dessus comme String === a, ou String.===(a).

Enfin, il existe également une clause else que vous pouvez utiliser lorsqu’il n’y a pas de correspondance.

case my_objectwhen String "This is a string"else "I have no idea what this is"end

L’opérateur triple égal (===)

Par défaut, case utilise l’opérateur triple égal (===) pour effectuer la comparaison.

Le problème avec === est qu’il n’a rien à voir avec l’égalité. Par défaut, il est aliasé à l’opérateur double equals (==) qui vérifie normalement si deux objets ont une valeur équivalente, mais il peut être défini pour signifier n’importe quoi.

Par exemple, une plage le définit comme un alias pour includes?, un regex le définit comme un alias pour match, une classe pour is_a?, un proc pour call. Vous voyez l’idée.

Cet opérateur fonctionne comme prévu avec les littéraux, mais pas avec les classes :

1 === 1 # => trueNumeric === Numeric # => false

C’est parce que le === est un alias pour kind_of?. Et voici la docs pour kind_of?.

kind_of ?(class) → true or false

Retourne true si class est la classe d’obj, ou si class est une des superclasses d’obj ou des modules inclus dans obj.

Cela signifie que si vous voulez faire un case ... when sur la classe d’un objet, cela ne fonctionnera pas :

obj = 'Hi'case obj.classwhen String "It's a string"end

C’est parce que, cela se traduit par String === String. Et cela renvoie false.

L’opérateur par défaut

L’expression case a un opérateur par défaut. Et cela signifie que vous n’avez pas besoin de le spécifier. C’est très bien, car vous pouvez simplement écrire when String et il utilise par défaut l’opérateur ===.

Mais, il y a des moments où vous voulez utiliser un opérateur différent. Et Ruby vous permet de le faire. Voici comment.

casewhen a < 3 "Smaller than 3"end

Case is an expression

Comme son nom l’indique, l’ensemble est une expression. Cela signifie qu’il s’évalue à une valeur. Vous pouvez donc affecter le résultat de l’expression entière case à une variable, comme ceci .

value = case when a < 3 "Smaller than 3" end

Il n’y a pas de chute

Si vous venez d’autres langages, vous avez probablement utilisé une déclaration switch ou quelque chose de similaire, et vous avez remarqué que case n’utilise pas de mots-clés comme break pour rompre le flux.

C’est parce qu’il n’y a pas de retombée avec case. Il renvoie simplement la valeur de l’expression qui a été mise en correspondance et c’est tout.

Multiples correspondances

Jusqu’à présent, vous n’avez utilisé qu’une seule valeur pour la clause when. Mais vous pouvez utiliser plusieurs valeurs.

case awhen 1..3 "Small number"end

Matching regexes

Vous pouvez utiliser les expressions case pour faire correspondre n’importe quoi. Mais au cas où ce ne serait pas évident, vous pourriez aussi faire correspondre des regex, ou des lambdas. Voici un exemple.

even = ->(x) { x % 2 == 0 }case awhen even "It's even"when /^+$/ "It's an integer"end

Définissez les vôtres

Un des faits les moins connus est que vous pouvez définir vos propres comparateurs.

Text = Struct.new(:min_length) do def ===(string) string.size > min_length && string.is_a?(String) endendcase awhen Text.new(100) "It's text"end

Dans l’exemple ci-dessus, si a est une chaîne de plus de 100 caractères, alors l’expression case retournera It's text.

Utiliser le polymorphisme à la place

Je ne vais pas m’étendre ici sur les avantages de la POO, vous pouvez en savoir plus à ce sujet dans l’article Programmation orientée objet avec Ruby, mais je vais vous montrer comment vous pouvez utiliser le polymorphisme pour remplacer une expression case.

La version cas

class Person attr_reader :country def initialize(country) @country = country end def nationality case country when "USA" "This guy is an American" when "Romania" "This guy is a Romanian" end endendjohn = Person.new("USA")puts john.nationality # => This guy is an American

La version POO

class Person attr_reader :country def initialize(country) @country = country end def nationality country.nationality endendclass America def nationality "This guy is an American" endendclass Romania def nationality "This guy is a Romanian" endendjohn = Person.new(America.new)puts john.nationality # => This guy is an American

C’est une bonne idée de supprimer autant de code de contrôle de flux (i.c’est-à-dire ifs, et case expressions) que possible. Cela améliore le respect du principe de responsabilité unique et rend le programme plus lisible en général.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *