nil 的安全导航运算符 (&.)
Safe navigation operator (&.) for nil
由于 Ruby 2.3 引入了安全导航运算符(&.
),a.k.a 孤独运算符,nil
对象上的行为似乎很奇怪。
nil.nil? # => true
nil&.nil? # => nil
是这样设计的吗?或者在添加孤独运算符时遗漏了一些边缘情况?
对于 foo && foo.bar
,foo&.bar
是 shorthand,那么您期望表达式 nil && nil.nil?
的结果是什么?
这是因为 nil&.nil?
对于 nil && nil.nil?
是 shorthand。这将评估为 nil && true
,然后是 nil
。
对于 x
. 的任何值,(nil && x).nil?
始终计算为 true
虽然语法很强大,但这个特定案例有可能成为开发人员的'gotcha':
(stuff&.things).nil?
=> 这会产生 true
如果东西不存在,或者 stuff.things
returns nil
.
对比以下情况:
stuff&.things&.nil?
=> 这在每种情况下都会产生 nil
除了 stuff.things
return 不是 nil
的情况,在这种情况下会 return false
。
由于区分 false
和 nil
的普通布尔逻辑存在困难,因此这在普通逻辑中不太可能有意义。
safe navigation operator:
告诉 Ruby 只有在接收者不为零时才调用下一个方法。否则,表达式 returns nil.
class 花名册
attr_accessor:球员
结束
class Player
attr_accessor :name, :position
def initialize(name, position)
@name = name
@position = position
end
end
有了这两个对象,我们就可以创建一个 2 对 2 女子篮球锦标赛的名单:
moore = Player.new("Maya Moore", "Forward")
taurasi = Player.new("Diana Taurasi", "Guard")
tourney_roster1 = Roster.new
tourney_roster1.players = [moore, taurasi]
如果我们想知道我们 2 对 2 球队的前锋,我们可能会这样找到名字:
if tourney_roster1.players.first.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
但如果我们的对手名单设置不正确怎么办?
tourney_roster2 = Roster.new
if tourney_roster2.players.first.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
tourney_roster2 尚未设置任何玩家。前面的代码将引发 NoMethodError 因为 tourney_roster2.players returns nil。我们可以添加条件语句来避免这种情况,但这会使我们的 if 语句冗长且不清楚:
if tourney_roster2.players &&
tourney_roster2.players.first &&
tourney_roster2.players.first.position == "Forward"
相反,我们可以使用安全导航运算符来避免 NoMethodError:
if tourney_roster2.players&.first&.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
一些合法的用例: 安全导航运算符在处理多个对象(如此处所示)以及将方法链接在一起时派上用场。
由于 Ruby 2.3 引入了安全导航运算符(&.
),a.k.a 孤独运算符,nil
对象上的行为似乎很奇怪。
nil.nil? # => true
nil&.nil? # => nil
是这样设计的吗?或者在添加孤独运算符时遗漏了一些边缘情况?
foo && foo.bar
,foo&.bar
是 shorthand,那么您期望表达式 nil && nil.nil?
的结果是什么?
这是因为 nil&.nil?
对于 nil && nil.nil?
是 shorthand。这将评估为 nil && true
,然后是 nil
。
x
. 的任何值,(nil && x).nil?
始终计算为 true
虽然语法很强大,但这个特定案例有可能成为开发人员的'gotcha':
(stuff&.things).nil?
=> 这会产生 true
如果东西不存在,或者 stuff.things
returns nil
.
对比以下情况:
stuff&.things&.nil?
=> 这在每种情况下都会产生 nil
除了 stuff.things
return 不是 nil
的情况,在这种情况下会 return false
。
由于区分 false
和 nil
的普通布尔逻辑存在困难,因此这在普通逻辑中不太可能有意义。
safe navigation operator:
告诉 Ruby 只有在接收者不为零时才调用下一个方法。否则,表达式 returns nil.
class 花名册 attr_accessor:球员 结束
class Player
attr_accessor :name, :position
def initialize(name, position)
@name = name
@position = position
end
end
有了这两个对象,我们就可以创建一个 2 对 2 女子篮球锦标赛的名单:
moore = Player.new("Maya Moore", "Forward")
taurasi = Player.new("Diana Taurasi", "Guard")
tourney_roster1 = Roster.new
tourney_roster1.players = [moore, taurasi]
如果我们想知道我们 2 对 2 球队的前锋,我们可能会这样找到名字:
if tourney_roster1.players.first.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
但如果我们的对手名单设置不正确怎么办?
tourney_roster2 = Roster.new
if tourney_roster2.players.first.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
tourney_roster2 尚未设置任何玩家。前面的代码将引发 NoMethodError 因为 tourney_roster2.players returns nil。我们可以添加条件语句来避免这种情况,但这会使我们的 if 语句冗长且不清楚:
if tourney_roster2.players &&
tourney_roster2.players.first &&
tourney_roster2.players.first.position == "Forward"
相反,我们可以使用安全导航运算符来避免 NoMethodError:
if tourney_roster2.players&.first&.position == "Forward"
puts "Forward: #{tourney_roster1.players.first.name}"
end
一些合法的用例: 安全导航运算符在处理多个对象(如此处所示)以及将方法链接在一起时派上用场。