Відповіді:
Його називають оператором безпечної навігації. Введений у 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