我偶然发现了这行ruby代码。什么&。这是什么意思?

@object&.method

当前回答

注意:尽管@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、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问题跟踪器上的特性介绍讨论。

其他回答

object&。An_attribute在ruby on rails?

我是Ruby on rails的新手,我看到了这种代码,但我不理解它:

在Ruby中,像大多数主流编程语言一样,用户代码不能修改编程语言的基本工作方式,也不能改变编程语言的语法。

因为Ruby on Rails只是Ruby代码,所以很明显这与Ruby on Rails没有任何关系。

因此,我们需要从Ruby中寻找解释,而不是Ruby on Rails。

安全导航操作符或安全导航器在language/safe_navigator_spec中指定。ruby/spec的Rb,特别是这里:

Context“当Context为nil时”做 它“总是返回nil” eval(“nil&.unknown”)。应该== nil eval(“[][10]&.unknown”)。应该== nil 结束 它“可以被拴住” eval(“nil&.one&.two&.three”)。应该== nil 结束 它“不评估论点” obj = Object.new obj.should_not_receive(米): Eval ("nil&.unknown(obj.m) {obj. xml ")m}”) 结束 结束

它被记录在Ruby语法文档的调用方法部分:

&。,称为“安全导航操作符”,允许在接收器为nil时跳过方法调用。如果跳过调用,它将返回nil并且不计算方法的参数。

它被称为安全导航操作员。在Ruby 2.3.0中引入,它让你可以在对象上调用方法,而不用担心对象可能是nil(避免nil的未定义方法:NilClass错误),类似于Rails中的try方法。

所以你可以写

@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给出了一个清晰而完整的答案,但我想添加更多的背景知识,并添加一个关于它与非实例变量使用的重要说明。


它被称为“安全导航操作符”(又名“可选链接操作符”,“空条件操作符”等)。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、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问题跟踪器上的特性介绍讨论。

它用于nil检查,如在kotlin和swift中 例如; 与对象-> Swift和Kotlin

model = car?.model

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

model = car&.model

如果使用汽车。模型没有&号,如果模型为空,系统不能继续运行。

小心!虽然安全导航操作符很方便,但也很容易欺骗自己用它改变逻辑。我建议避免在流量控制中使用它。例子:

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