Я столкнулся с этой строкой кода ruby. Что означает &.
в этом?
@object&.method
Я столкнулся с этой строкой кода ruby. Что означает &.
в этом?
@object&.method
Это называется оператор безопасной навигации. Представленный в Ruby 2.3.0, он позволяет вызывать методы для объектов, не беспокоясь о том, что объект может иметь значение nil
(undefined method for nil:NilClass
ошибки 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
Чтобы устранить эту проблему, проверьте, определена ли ваша локальная переменная, или установите ее в 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 и т.д. Однако общий синтаксис ?.
(question dot). Но этот синтаксис не был принят 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?
никогда не вызывается, в результате чего выполняется оператор puts
. Во втором примере, однако, str&.empty?
возвращает nil
, что неверно, и оператор puts
никогда не выполняется.
он используется для проверки на ноль, например, в kotlin и swift; с объектом → Свифт и Котлин
model = car?.model
эта модель может быть nil (Swift) или null (Kotlin), если мы не определили значение модели в классе автомобиля. мы используем этот амперсанд вместо знака вопроса в рубине
model = car&.model
если использовать car.model без амперсанда и если модель равна нулю, система не сможет продолжить работу.