216

我遇到了这行 ruby​​ 代码。这&.意味着什么?

@object&.method
4

4 回答 4

284

它被称为安全导航操作员。在 Ruby 2.3.0 中引入,它允许您调用对象上的方法,而不必担心对象可能是nil(避免undefined method for nil:NilClass错误),类似于tryRails 中的方法

所以你可以写

@person&.spouse&.name

代替

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

文档

my_object.my_method

这会将my_method消息发送到my_object。任何对象都可以是接收者,但根据发送消息的方法的可见性,可能会引发NoMethodError.

你可以用&.来指定一个接收者, thenmy_method不被调用,结果是nil当接收者是nil. 在这种情况下,my_method不会评估 的参数。

于 2016-04-23T15:23:53.290 回答
76

注意:尽管@Santosh 给出了明确而完整的答案,但我想添加更多背景知识并添加关于其与非实例变量一起使用的重要说明。


它被称为“安全导航运算符”(又名“可选链运算符”、“空条件运算符”等)。Matz 似乎称其为“孤独的经营者”。它是在 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内部使用方法来调用方法。Matz 建议它很慢,这应该是一个内置的语言特性。

许多其他编程语言具有类似的功能: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 问题跟踪器上的此功能介绍讨论。

于 2016-04-23T16:32:11.433 回答
8

警惕!尽管安全导航操作符很方便,但它也可以很容易地欺骗自己改变逻辑。我建议避免在流量控制中使用它。例子:

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语句永远不会执行。

于 2018-02-07T15:13:25.183 回答
4

它用于 nil 检查,例如在 kotlin 和 swift 中;使用 Object -> Swift 和 Kotlin

model = car?.model

如果我们没有在 car 类中定义模型值,这个模型可以是 nil(Swift) 或 null(Kotlin)。我们在 ruby​​ 中使用 & 号而不是问号

model = car&.model

如果使用不带 & 的 car.model 并且如果 model 为 nil,则系统无法继续运行。

于 2019-01-21T03:26:48.800 回答