Antworten:
Es wird als sicherer Navigationsoperator bezeichnet. Mit der in Ruby 2.3.0 eingeführten Methode können Sie Methoden für Objekte aufrufen, ohne befürchten zu müssen, dass das Objekt ähnlich ist nil
( undefined method for nil:NilClass
Fehler vermeiden ), ähnlich der try
Methode in Rails .
So können Sie schreiben
@person&.spouse&.name
anstatt
@person.spouse.name if @person && @person.spouse
Aus den Dokumenten :
my_object.my_method
Dadurch wird die Nachricht my_method an my_object gesendet. Jedes Objekt kann ein Empfänger sein, aber abhängig von der Sichtbarkeit der Methode kann das Senden einer Nachricht einen NoMethodError auslösen.
Sie können & verwenden. Um einen Empfänger zu bestimmen, wird my_method nicht aufgerufen und das Ergebnis ist null, wenn der Empfänger null ist. In diesem Fall werden die Argumente von my_method nicht ausgewertet.
Hinweis: Auch wenn @Santosh eine klare und vollständige Antwort gegeben hat, möchte ich weitere Hintergrundinformationen hinzufügen und einen wichtigen Hinweis zur Verwendung mit Nichtinstanzvariablen hinzufügen .
Es wird als " sicherer Navigationsoperator " bezeichnet (auch bekannt als "optionaler Verkettungsoperator", "nullbedingter Operator" usw. ). Matz scheint es "einsamer Operator" zu nennen. Es wurde in Ruby 2.3 eingeführt . Es sendet eine Methode nur dann an ein Objekt, wenn dies nicht der Fall ist nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Bitte beachten Sie, dass der obige Code Instanzvariablen verwendet. Wenn Sie einen sicheren Navigationsoperator mit lokalen Variablen verwenden möchten, müssen Sie zuerst überprüfen, ob Ihre lokalen Variablen definiert sind.
# `user` local variable is not defined previous
user&.profile
# This code would throw the following error:
NameError: undefined local variable or method `user' for main:Object
Um dieses Problem zu beheben, überprüfen Sie, ob Ihre lokale Variable zuerst definiert wurde, oder setzen Sie sie auf Null:
# Option 1: Check the variable is defined
if defined?(user)
user&.profile
end
# Option 2: Define your local variable. Example, set it to nil
user = nil
user&.profile # Works and does not throw any errors
Rails hat eine try
Methode, die im Grunde das Gleiche tut. Es verwendet send
intern eine Methode, um eine Methode aufzurufen. Matz schlug vor, dass es langsam ist und dies eine integrierte Sprachfunktion sein sollte.
Viele andere Programmiersprachen haben ähnliche Funktionen: Ziel C, Swift, Python, Scala, CoffeeScript usw. Eine gebräuchliche Syntax ist jedoch ?.
(Fragepunkt). Diese Syntax konnte jedoch von Ruby nicht übernommen werden. Da ?
in Methodennamen erlaubt war und somit die ?.
Symbolfolge bereits ein gültiger Ruby-Code ist. Beispielsweise:
2.even?.class # => TrueClass
Deshalb musste sich die Ruby-Community eine andere Syntax einfallen lassen. Es war eine aktive Diskussion und verschiedene Optionen in Betracht gezogen wurden ( .?
, ?
, &&
, etc.). Hier ist eine Liste einiger Überlegungen:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Bei der Auswahl der Syntax haben sich die Entwickler verschiedene Randfälle angesehen, und die Diskussion ist sehr nützlich. Wenn Sie alle Varianten und Nuancen des Bedieners durchgehen möchten, lesen Sie bitte diese Diskussion zur Einführung in den offiziellen Ruby Issue Tracker.
.?
und andere Optionen in Betracht gezogen wurden, wurde aber &.
gewählt! Also wird nur &.
funktionieren.
&.
und nicht .?
, mein schlechtes. Meine Antwort wurde aktualisiert. Danke für die Warnung!
user.?profile
sollte sein user&.profile
(konnte es nicht selbst bearbeiten, da es nur eine 1-Zeichen-Bearbeitung ist!).
Sei vorsichtig! Obwohl der sichere Navigationsoperator praktisch ist, kann es auch einfach sein, sich dazu zu verleiten, Ihre Logik damit zu ändern. Ich empfehle, die Verwendung in der Flusskontrolle zu vermeiden. Beispiel:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
Im ersten Beispiel wird str.nil?
zurückgegeben true
und str.empty?
nie aufgerufen, wodurch die puts
Anweisung ausgeführt wird. Im zweiten Beispiel jedoch str&.empty?
kehrt nil
die Falsey ist, und die puts
Anweisung wird nie ausgeführt.
str.nil?
wahr ist (wie Sie sagen), was bedeutet, str.empty?
dass sie überhaupt nicht aufgerufen wird (so funktioniert der ||
Operator). Der Rest Ihrer Aussage ist richtig.
puts "hello" unless str&.present?
(Schienen nur für die vorliegende Methode) gültig
es wird für Null-Check verwendet, wie zum Beispiel in Kotlin und Swift; mit Objekt -> Swift und Kotlin
model = car?.model
Dieses Modell kann null (Swift) oder null (Kotlin) sein, wenn wir den Modellwert in der Fahrzeugklasse nicht definiert haben. Wir verwenden dieses kaufmännische Und anstelle des Fragezeichens in Ruby
model = car&.model
Wenn Sie car.model ohne kaufmännisches Und verwenden und das Modell Null ist, kann das System nicht weiter ausgeführt werden.
try!
Methode, nichttry