Відповіді:
Його називають оператором безпечної навігації. Введений у Ruby 2.3.0, він дозволяє викликати методи на об’єктах, не переживаючи, що об’єктом може бути nil(Уникнення undefined method for nil:NilClassпомилки), аналогічно tryметоду в Rails .
Тож можна писати
@person&.spouse&.name
замість
@person.spouse.name if @person && @person.spouse
З Документів :
my_object.my_methodЦе надсилає повідомлення my_method до my_object. Будь-який об'єкт може бути приймачем, але залежно від видимості способу надсилання повідомлення може викликати NoMethodError.
Ви можете використовувати &. для позначення приймача, тоді my_method не викликається, і результат є нульовим, коли приймач дорівнює нулю. У цьому випадку аргументи my_method не оцінюються.
Примітка. Хоча @Santosh дав чітку і повну відповідь, я хотів би додати ще деяку інформацію та додати важливу примітку щодо її використання із змінними, які не є примірниками.
Він називається " Оператор безпечної навігації " (він же "Операційний необов'язковий оператор", "Нульовий умовний оператор" тощо ). Мац, здається, називає це "одиноким оператором". Він був представлений у Ruby 2.3 . Він посилає метод об’єкту, лише якщо його немає nil.
# Call method `.profile` on `user` only if `user` is not `nil`
@user&.profile
# Equivalent to
unless @user.nil?
@user.profile
end
Зверніть увагу: вищевказаний код використовує змінні екземпляри. Якщо ви хочете використовувати безпечний навігаційний оператор з локальними змінними, вам доведеться спочатку перевірити, чи визначені ваші локальні змінні.
# `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
Щоб виправити цю проблему, перевірте, чи локальна змінна визначена спочатку або встановіть її на нуль:
# 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 має tryметод, який в основному робить те саме. Він використовує sendметод внутрішньо для виклику методу. Мац припустив, що це повільно, і це має бути вбудованою мовною функцією.
Багато інших мов програмування мають подібну особливість: Objective C, Swift, Python, Scala, CoffeeScript тощо. Однак загальним синтаксисом є ?.(питання питання). Але Рубі не зміг прийняти цей синтаксис. Оскільки це ?було дозволено в назвах методів, і таким чином, ?.послідовність символів - це вже дійсний код Ruby. Наприклад:
2.even?.class # => TrueClass
Ось чому спільнота Ruby повинна була придумувати різні синтаксиси. Це було активне обговорення і були розглянуті різні варіанти ( .?, ?, &&і т.д.). Ось перелік деяких міркувань:
u.?profile.?thumbnails
u\profile\thumbnails
u!profile!thumbnails
u ? .profile ? .thumbnails
u && .profile && .thumbnails
# And finally
u&.profile&.thumbnails
Вибираючи синтаксис, розробники розглядали різні кращі випадки, і обговорення цілком корисно пройти. Якщо ви хочете пройти всі варіанти та нюанси оператора, будь ласка, ознайомтесь із обговоренням цієї функції щодо офіційного трекера випуску Ruby.
.?і інші варіанти були розглянуті, але &.обрані! Отже, тільки &.буде працювати.
&.і ні .?, моя погана. Оновлено мою відповідь. Дякую за голову вгору!
user.?profileслід user&.profile(не можу сам редагувати його, оскільки це лише редакція в 1 символ!).
Будьте обережні! Хоча оператору безпечної навігації зручно, це також може бути легко ввести себе в зміну логіки. Я рекомендую уникати використання його для контролю потоку. Приклад:
str = nil
puts "Hello" if str.nil? || str.empty?
# The above line is different than the below line
puts "Hello" if str&.empty?
У першому прикладі str.nil?повертається trueі str.empty?ніколи не викликається, що призводить до виконання putsзаяви. У другому прикладі, однак, str&.empty?повертається nilфальсифікат, а putsзаява ніколи не виконується.
str.nil?є правдивим (як ви кажете), що означає str.empty?, що насправді взагалі не буде викликано (саме так ||працює оператор). Решта ваших тверджень правильна.
puts "hello" unless str&.present?(рейки тільки для теперішнього методу)
він використовується для нульової перевірки, наприклад у kotlin та swift; з Об'єктом -> Свіфт і Котлін
model = car?.model
ця модель може бути нульовою (Swift) або null (Kotlin), якщо ми не визначили значення моделі в автомобільному класі. ми використовуємо цей символ замість знака питання в рубіні
model = car&.model
якщо використовувати car.model без ampersand і якщо модель є нульовою, система не може продовжувати працювати.
try!метод, а неtry