Recherche…


Remarques

Les opérateurs sont des méthodes

La plupart des opérateurs ne sont en fait que des méthodes, donc x + y appelle la méthode + de x avec l'argument y , qui serait écrit x.+(y) . Si vous écrivez une méthode qui a une signification sémantique pour un opérateur donné, vous pouvez implémenter votre variante dans la classe.

Comme un exemple stupide:

# A class that lets you operate on numbers by name.
class NamedInteger
  name_to_value = { 'one' => 1, 'two' => 2, ... }

  # define the plus method
  def + (left_addend, right_addend)
    name_to_value(left_addend) + name_to_value(right_addend)
  end

  ...
end

Quand utiliser && contre and , || vs or

Notez qu'il y a deux façons d'exprimer les booléens, soit && ou and , et || ou or - ils sont souvent interchangeables, mais pas toujours. Nous nous référerons à ceux-ci en tant que variantes "caractère" et "mot".

Les variantes de caractères ont une priorité plus élevée, ce qui évite les erreurs inattendues.

Les variantes de mot étaient à l'origine destinées aux opérateurs de flux de contrôle plutôt qu'aux opérateurs booléens. Autrement dit, ils ont été conçus pour être utilisés dans des instructions de méthode chaînées:

raise 'an error' and return

Bien qu'ils puissent être utilisés comme opérateurs booléens, leur priorité inférieure les rend imprévisibles.

Deuxièmement, beaucoup de rubyistes préfèrent la variante de caractère lors de la création d'une expression booléenne (celle qui est évaluée comme true ou false ) telle que x.nil? || x.empty? . En revanche, les variantes de mots sont préférables dans les cas où une série de méthodes sont en cours d’évaluation, et une autre peut échouer. Par exemple, un idiome commun utilisant la variante de mot pour les méthodes renvoyant nil en cas d'échec pourrait ressembler à ceci:

def deliver_email
  # If the first fails, try the backup, and if that works, all good
  deliver_by_primary or deliver_by_backup and return
  # error handling code
end

Priorité et méthodes de l'opérateur

Du plus haut au plus bas, c'est le tableau de priorité pour Ruby. Les opérations de haute priorité ont lieu avant les opérations de faible priorité.

╔═══════════════════════╦════════════════════════════════════════╦═════════╗
║ Operators             ║                 Operations             ║ Method? ║
╠═══════════════════════╬════════════════════════════════════════╬═════════╣
║ .                     ║ Method call (e.g. foo.bar)             ║         ║
║ []  []=               ║ Bracket Lookup, Bracket Set            ║    ✓¹   ║
║ ! ~ +                 ║ Boolean NOT, complement, unary plus    ║    ✓²   ║
║ **                    ║ Exponentiation                         ║    ✓    ║
║ -                     ║ Unary minus                            ║    ✓²   ║
║ * / %                 ║ Multiplication, division, modulo       ║    ✓    ║
║ + -                   ║ Addition, subtraction                  ║    ✓    ║
║ << >>                 ║ Bitwise shift                          ║    ✓    ║
║ &                     ║ Bitwise AND                            ║    ✓    ║
║ | ^                   ║ Bitwise OR, Bitwise XOR                ║    ✓    ║
║ < <= >= >             ║ Comparison                             ║    ✓    ║
║ <=> == != === =~ !~   ║ Equality, pattern matching, comparison ║    ✓³   ║
║ &&                    ║ Boolean AND                            ║         ║
║ ||                    ║ Boolean OR                             ║         ║
║ .. ...                ║ Inclusive range, Exclusive range       ║         ║
║ ? :                   ║ Ternary operator                       ║         ║
║ rescue                ║ Modifier rescue                        ║         ║
║ = += -=               ║ Assignments                            ║         ║
║ defined?              ║ Defined operator                       ║         ║
║ not                   ║ Boolean NOT                            ║         ║
║ or and                ║ Boolean OR, Boolean AND                ║         ║
║ if unless while until ║ Modifier if, unless, while, until      ║         ║
║ { }                   ║ Block with braces                      ║         ║
║ do end                ║ Block with do end                      ║         ║
╚═══════════════════════╩════════════════════════════════════════╩═════════╝

Unary + et unary - sont pour +obj , -obj ou -(some_expression) .

Modifier-if, modifier-sauf, etc. sont pour les versions modificateur de ces mots-clés. Par exemple, il s'agit d'un modificateur sauf si l'expression:

a += 1 unless a.zero?

Les opérateurs avec un ✓ peuvent être définis comme des méthodes. La plupart des méthodes sont nommées exactement comme l'opérateur est nommé, par exemple:

class Foo
  def **(x)
    puts "Raising to the power of #{x}"
  end
  def <<(y)
    puts "Shifting left by #{y}"
  end
  def !
    puts "Boolean negation"
  end
end

Foo.new ** 2     #=> "Raising to the power of 2"
Foo.new << 3     #=> "Shifting left by 3"
!Foo.new         #=> "Boolean negation"

¹ Les méthodes Bracket Lookup et Bracket Set ( [] et []= ) ont leurs arguments définis après le nom, par exemple:

class Foo
  def [](x)
    puts "Looking up item #{x}"
  end
  def []=(x,y)
    puts "Setting item #{x} to #{y}"
  end
end

f = Foo.new
f[:cats] = 42    #=> "Setting item cats to 42"
f[17]            #=> "Looking up item 17"

² Les opérateurs "unaire plus" et "unaire moins" sont définis comme des méthodes nommées +@ et -@ , par exemple

class Foo
  def -@
    puts "unary minus"
  end
  def +@
    puts "unary plus"
  end
end

f = Foo.new
+f               #=> "unary plus"
-f               #=> "unary minus"

³ Dans les premières versions de Ruby, l'opérateur d'inégalité != Et l'opérateur sans correspondance !~ Ne pouvaient pas être définis comme des méthodes. Au lieu de cela, la méthode pour l'opérateur d'égalité correspondant == ou l'opérateur correspondant =~ été invoquée, et le résultat de cette méthode a été booléen inversé par Ruby.

Si vous ne définissez pas vos propres opérateurs != Ou !~ , Le comportement ci-dessus est toujours vrai. Cependant, à partir de Ruby 1.9.1, ces deux opérateurs peuvent également être définis comme des méthodes:

class Foo
  def ==(x)
    puts "checking for EQUALITY with #{x}, returning false"
    false
  end
end

f = Foo.new
x = (f == 42)    #=> "checking for EQUALITY with 42, returning false"
puts x           #=> "false"
x = (f != 42)    #=> "checking for EQUALITY with 42, returning false"
puts x           #=> "true"

class Foo
  def !=(x)
    puts "Checking for INequality with #{x}"
  end
end

f != 42          #=> "checking for INequality with 42"

Opérateur d'égalité de cas (===)

Aussi connu sous le nom de triple equals .

Cet opérateur ne teste pas l'égalité, mais teste plutôt si l'opérande droit a une relation IS A avec l'opérande gauche. En tant que tel, l' opérateur d'égalité de noms populaire est trompeur.

Cette réponse SO le décrit ainsi: la meilleure façon de décrire a === b est "si j'ai un tiroir étiqueté a , est-il judicieux d'y mettre b ?" En d'autres termes, l'ensemble a inclut-il le membre b ?

Exemples ( source )

(1..5) === 3            # => true
(1..5) === 6            # => false

Integer === 42          # => true
Integer === 'fourtytwo' # => false

/ell/ === 'Hello'       # => true
/ell/ === 'Foobar'      # => false

Classes qui remplacent ===

De nombreuses classes remplacent === pour fournir une sémantique significative dans les instructions de cas. Certains d'entre eux sont:

╔═════════════════╦════════════════════╗
║      Class      ║     Synonym for    ║
╠═════════════════╬════════════════════╣
║ Array           ║ ==                 ║
║                 ║                    ║
║ Date            ║ ==                 ║
║                 ║                    ║
║ Module          ║ is_a?              ║
║                 ║                    ║
║ Object          ║ ==                 ║
║                 ║                    ║
║ Range           ║ include?           ║
║                 ║                    ║
║ Regexp          ║ =~                 ║
║                 ║                    ║
║ String          ║ ==                 ║
╚═════════════════╩════════════════════╝

Pratique recommandée

L'utilisation explicite de l'opérateur d'égalité de casse === doit être évitée. Il ne teste pas l'égalité, mais plutôt la subsomption , et son utilisation peut être source de confusion. Le code est plus clair et plus facile à comprendre lorsque la méthode synonyme est utilisée à la place.

# Bad
Integer === 42
(1..5) === 3
/ell/ === 'Hello'

# Good, uses synonym method
42.is_a?(Integer)
(1..5).include?(3)
/ell/ =~ 'Hello'

Opérateur de navigation sécurisé

Ruby 2.3.0 a ajouté l' opérateur de navigation sécurisé , &. . Cet opérateur est destiné à raccourcir le paradigme de l' object && object.property && object.property.method dans les instructions conditionnelles.

Par exemple, vous avez un objet House avec une propriété address et vous voulez trouver le street_name partir de l' address . Pour programmer cela en toute sécurité afin d’éviter les erreurs nuls dans les anciennes versions de Ruby, vous utiliseriez le code suivant:

if house && house.address && house.address.street_name
  house.address.street_name
end

L'opérateur de navigation sécurisé réduit cette condition. Au lieu de cela, vous pouvez écrire:

if house&.address&.street_name
  house.address.street_name
end

Mise en garde:
L'opérateur de navigation sécurisé n'a pas exactement le même comportement que le conditionnel chaîné. En utilisant le conditionnel chaîné (premier exemple), le bloc if ne serait pas exécuté si, par exemple, l' address était false . L'opérateur de navigation sécurisé ne reconnaît que des valeurs nil , mais autorise des valeurs telles que false . Si l' address est false , l'utilisation du SNO entraînera une erreur:

house&.address&.street_name
# => undefined method `address' for false:FalseClass


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow