Я наткнулся на эту строку кода рубина. Что здесь означает &.?

@object&.method

Ответы (4)

Он называется Оператором безопасной навигации. Представленный в Ruby 2.3.0, он позволяет вам вызывать методы для объектов, не беспокоясь о том, что объект может быть nil(избегая undefined метода для nil: NilClass error), аналогично попробуйте метод в Rails.

Так можно написать

@person&.spouse&.name

вместо

@person.spouse.name if @person && @person.spouse

Из Документов:

my_object.my_method

Это отправляет сообщение my_method на my_object. Любой объект может быть получателем, но в зависимости от видимости метода отправка сообщения может вызвать ошибку NoMethodError.

Вы можете использовать &. для обозначения получателя, тогда my_method не вызывается и результат будет nil, когда получатель nil. В этом случае аргументы 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

Чтобы исправить эту проблему, сначала проверьте, определена ли ваша локальная переменная, или установите для нее значение nil:

# 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. Поскольку ? было разрешено в именах методов и, следовательно, последовательность символов ?. уже является допустимым кодом 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.

Будьте осторожны! Хотя оператор безопасной навигации удобен, с его помощью можно легко обмануть себя и изменить свою логику. Я рекомендую избегать его использования при управлении потоком. Пример:

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? никогда не вызывается, в результате чего помещаетзаявление к исполнению. Однако во втором примере str & .empty? возвращает nil, что является ложным, а оператор put никогда не выполняется.

используется для проверки нуля, например, в kotlin и swift Например; с Object -> Swift и Kotlin

model = car?.model

эта модель может быть нулевой (Swift) или нулевой (Kotlin), если мы не определили значение модели в классе автомобиля. мы используем этот амперсанд вместо вопросительного знака в рубине

model = car&.model

при использовании car.model без амперсанда и при нулевом значении модели система не может продолжать работу.

2022 WebDevInsider