Ruby Language
operatörer
Sök…
Anmärkningar
Operatörer är metoder
De flesta operatörer är faktiskt bara metoder, så x + y
kallar +
-metoden för x
med argumentet y
, vilket skulle skrivas x.+(y)
. Om du skriver en egen metod som har semantisk betydelse av en given operatör kan du implementera din variant i klassen.
Som ett dumt exempel:
# 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
När &&
vs. and
, ||
mot or
Observera att det finns två sätt att uttrycka booleaner, antingen &&
eller and
, och ||
eller or
- de är ofta utbytbara, men inte alltid. Vi kommer att hänvisa till dessa som "karaktär" och "ord" varianter.
Karaktärvarianterna har högre prioritet så minska behovet av parenteser i mer komplexa påståenden hjälper till att undvika oväntade fel.
Ordet varianter var ursprungligen avsedda som kontrollflödesoperatörer snarare än booleska operatörer. Det vill säga de var designade för att användas i uttalade metoduttalanden:
raise 'an error' and return
Medan de kan användas som booleska operatörer, gör deras lägre prioritet dem oförutsägbara.
För det andra föredrar många rubinister karaktärvarianten när de skapar ett booleskt uttryck (ett som utvärderar till true
eller false
) som x.nil? || x.empty?
. Å andra sidan föredras ordvarianter i fall där en serie metoder utvärderas och en kan misslyckas. Till exempel kan en vanlig formspråk som använder ordvarianten för metoder som returnerar nil
vid misslyckande se ut:
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
Operatörens prioritet och metoder
Från högsta till lägsta är detta föregångstabellen för Ruby. Operationer med hög prioritet inträffar före operationer med låg prioritet.
╔═══════════════════════╦════════════════════════════════════════╦═════════╗
║ 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 + och unary - är för +obj
, -obj
eller -(some_expression)
.
Modifier-if, modifier-ONLY, etc. är för modifieringsversionerna av dessa nyckelord. Till exempel är detta en modifierare om inte uttrycket:
a += 1 unless a.zero?
Operatörer med ✓ kan definieras som metoder. De flesta metoder heter exakt som operatören heter, till exempel:
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"
Methods Metoderna Bracket Lookup and Bracket Set ( []
och []=
) har sina argument definierade efter namnet, till exempel:
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"
² Operatörerna "unary plus" och "unary minus" definieras som metoder med namnet +@
och -@
, till exempel
class Foo
def -@
puts "unary minus"
end
def +@
puts "unary plus"
end
end
f = Foo.new
+f #=> "unary plus"
-f #=> "unary minus"
³ I tidiga versioner av Ruby kunde ojämlikhetsoperatören !=
Och den icke-matchande operatören !~
Inte definieras som metoder. Istället åberopades metoden för motsvarande jämställdhetsoperatör ==
eller matchande operatör =~
, och resultatet av den metoden boolesiska inverterades av Ruby.
Om du inte definierar dina egna !=
Eller !~
Operatörer är ovanstående beteende fortfarande sant. Från Ruby 1.9.1 kan emellertid dessa två operatörer också definieras som metoder:
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"
Ärende jämställdhetsoperatör (===)
Även känd som trippel lika .
Denna operatör testar inte jämställdhet, utan testar snarare om den högra operanden har en IS A-relation med den vänstra operanden. Som sådan är den populära namnet likabehandlingsoperatören vilseledande.
Detta SO-svar beskriver det så: det bästa sättet att beskriva a === b
är "om jag har en låda märkt a
, är det meningsfullt att lägga b
i den?" Med andra ord inkluderar uppsättningen a
medlemmen b
?
Exempel ( källa )
(1..5) === 3 # => true
(1..5) === 6 # => false
Integer === 42 # => true
Integer === 'fourtytwo' # => false
/ell/ === 'Hello' # => true
/ell/ === 'Foobar' # => false
Klasser som åsidosätter ===
Många klasser åsidosätter ===
att tillhandahålla meningsfull semantik i uttalanden. Några av dem är:
╔═════════════════╦════════════════════╗
║ Class ║ Synonym for ║
╠═════════════════╬════════════════════╣
║ Array ║ == ║
║ ║ ║
║ Date ║ == ║
║ ║ ║
║ Module ║ is_a? ║
║ ║ ║
║ Object ║ == ║
║ ║ ║
║ Range ║ include? ║
║ ║ ║
║ Regexp ║ =~ ║
║ ║ ║
║ String ║ == ║
╚═════════════════╩════════════════════╝
Rekommenderad praxis
Explicit användning av operatören om jämställdhet ===
bör undvikas. Det testar inte jämställdhet utan snarare subumption , och dess användning kan vara förvirrande. Koden är tydligare och lättare att förstå när synonymmetoden används istället.
# Bad
Integer === 42
(1..5) === 3
/ell/ === 'Hello'
# Good, uses synonym method
42.is_a?(Integer)
(1..5).include?(3)
/ell/ =~ 'Hello'
Safe Navigation Operator
Ruby 2.3.0 lade till den säkra navigeringsoperatören &.
. Den här operatören är avsedd att förkorta paradigmet för object && object.property && object.property.method
i villkorade uttalanden.
Till exempel, har du House
objekt med en address
egendom, och du vill hitta street_name
från address
. För att programmera detta på ett säkert sätt för att undvika noll-fel i äldre Ruby-versioner, skulle du använda kod något liknande:
if house && house.address && house.address.street_name
house.address.street_name
end
Den säkra navigeringsoperatören förkortar detta villkor. Istället kan du skriva:
if house&.address&.street_name
house.address.street_name
end
Varning:
Den säkra navigeringsoperatören har inte exakt samma beteende som den kedjade villkoren. Med hjälp av den kedjade villkorade (första exemplet), if
blocket inte skulle köras om, säg address
var false
. Den säkra navigeringsoperatören känner bara till nil
, men tillåter värden som false
. Om address
är false
, använder SNO ett fel:
house&.address&.street_name
# => undefined method `address' for false:FalseClass