为什么方法中没有attr_accessor定义的变量?

时间:2013-11-23 18:03:44

标签: ruby

class A
 attr_accessor :rank
 def change_rank
   rank = rank + 1
 end
end

a = A.new
a.rank = 5
p a.rank
a.change_rank
p a.rank

为rank = rank + 1产生错误(未定义的方法+为nil:Nilclass)。不应该对“rank”方法的隐式调用返回实例变量@rank的值吗?出于某种原因,如果我将第4行更改为:

,则此代码有效
self.rank = self.rank + 1

为什么对rank方法的显式调用有效,而隐式方法没有?

2 个答案:

答案 0 :(得分:4)

 def change_rank
   rank = rank + 1
 end

在此上下文中,名称rank会将解析为attr_accessor生成的方法之一。红宝石大致认为这是:

 def change_rank
   rank = nil
   rank = rank + 1
 end

当ruby看到对“裸”名称的赋值时,它会创建一个具有此名称的局部变量。它将影响外部方法。由于本地变量已使用nil初始化,因此它解释了您遇到的错误。

您可以这样做以避免错误(明确您要修改的内容):

 def change_rank
   self.rank += 1
 end

更新

这里有更多代码说明了这个

defined?(x) # => nil # name x is unidentified yet
defined?(x = x) # => "assignment" # local var x is created by assignment
defined?(x) # => "local-variable" # now local var x exists
x # => nil # and its value is nil

答案 1 :(得分:0)

我重写你的代码如下。你可以看到Ruby如何以不同的方式对待rank =和排名。

class A
  attr_accessor :rank
  def change_rank
    self.rank = rank + 1
 end
end

a = A.new
a.rank = 5
p a.rank
a.change_rank
p a.rank

执行结果:

5
6