Odpowiedzi:
Nazywa się Operator Bezpiecznej Nawigacji. Wprowadzony w Ruby 2.3.0, pozwala na wywoływanie metod na obiektach bez obawy, że obiekt może być nil
(Unikanie undefined method for nil:NilClass
błędu), podobnie jak try
metoda w Railsach .
Więc możesz pisać
@person&.spouse&.name
zamiast
@person.spouse.name if @person && @person.spouse
Z Dokumentów :
my_object.my_method
Spowoduje to wysłanie wiadomości my_method do my_object. Każdy obiekt może być odbiornikiem, ale w zależności od widoczności metody wysłanie wiadomości może zgłosić NoMethodError.
Możesz użyć &. aby wyznaczyć odbiorcę, wówczas my_method nie jest wywoływana, a wynik jest zerowy, gdy odbiornik jest zerowy. W takim przypadku argumenty my_method nie są oceniane.
Uwaga: Mimo że @Santosh udzielił jasnej i pełnej odpowiedzi, chciałbym dodać więcej tła i dodać ważną uwagę dotyczącą jego użycia ze zmiennymi innymi niż instancje.
Nazywa się to „ Bezpiecznym operatorem nawigacji ” ( inaczej „Opcjonalny operator łańcuchowy”, „Operator warunkowy zerowy” itp .). Matz zdaje się nazywać to „samotnym operatorem”. Został wprowadzony w Rubim 2.3 . Wysyła metodę do obiektu tylko wtedy, gdy tak nie jest nil
.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Zwróć uwagę, że powyższy kod używa zmiennych instancji. Jeśli chcesz używać bezpiecznego operatora nawigacji ze zmiennymi lokalnymi, musisz najpierw sprawdzić, czy zmienne lokalne są zdefiniowane.
# `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
Aby rozwiązać ten problem, sprawdź, czy zmienna lokalna jest zdefiniowana jako pierwsza, lub ustaw ją na zero:
# 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
Railsy mają try
metodę, która w zasadzie robi to samo. Używa send
metody wewnętrznie do wywołania metody. Matz zasugerował, że jest to powolne i powinno to być wbudowaną funkcją języka.
Wiele innych języków programowania ma podobną funkcję: Objective C, Swift, Python, Scala, CoffeeScript itp. Jednak typową składnią jest ?.
(kropka zapytania). Ale Ruby nie mógł przyjąć tej składni. Ponieważ ?
było to dozwolone w nazwach metod, ?.
sekwencja symboli jest już poprawnym kodem Rubiego. Na przykład:
2.even?.class # => TrueClass
Dlatego społeczność Rubiego musiała wymyślić inną składnię. To była aktywna dyskusja i rozważono różne warianty ( .?
, ?
, &&
, itd.). Oto lista kilku uwag:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Wybierając składnię, programiści przyjrzeli się różnym skrajnym przypadkom i dyskusja jest bardzo przydatna. Jeśli chcesz przejrzeć wszystkie warianty i niuanse operatora, zapoznaj się z dyskusją wprowadzającą do funkcji dotyczącą oficjalnego narzędzia do śledzenia problemów w Rubim.
.?
i rozważono inne opcje, ale &.
wybrano! Więc tylko &.
zadziała.
&.
a nie .?
, moja wina. Zaktualizowałem moją odpowiedź. Dzięki za ostrzeżenie!
user.?profile
powinno być user&.profile
(nie mogłem tego samodzielnie edytować, ponieważ jest to edycja 1 znaku!).
Uważać! Chociaż bezpieczny operator nawigacji jest wygodny, można też łatwo oszukać siebie i zmienić za jego pomocą logikę. Zalecam unikanie używania tego w kontroli przepływu. Przykład:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
W pierwszym przykładzie str.nil?
zwraca true
i str.empty?
nigdy nie jest wywoływana, powodując wykonanie puts
instrukcji. Jednak w drugim przykładzie str&.empty?
zwraca wynik, nil
który jest fałszywy, a puts
instrukcja nigdy nie jest wykonywana.
str.nil?
jest prawda (jak mówisz), co oznacza, str.empty?
że w rzeczywistości nie zostanie w ogóle wywołany (tak ||
działa operator). Reszta twojego stwierdzenia jest poprawna.
puts "hello" unless str&.present?
(szyny tylko dla obecnej metody?)
używany do sprawdzenia zerowego, na przykład w kotlin i swift; z Object -> Swift i Kotlin
model = car?.model
ten model może być zerowy (Swift) lub zerowy (Kotlin), jeśli nie zdefiniowaliśmy wartości modelu w klasie samochodu. używamy tego ampersandu zamiast znaku zapytania w rubinie
model = car&.model
jeśli używasz car.model bez znaku ampersand i jeśli model jest zerowy, system nie może kontynuować pracy.
try!
metoda, a nietry