我最近被以下代码困扰:
class Foo
attr_accessor :n
def initialize(i)
@n = i
end
def val
n
end
def bump!
n += 1
end
end
f = Foo.new(0)
puts f.val
f.bump!
puts f.val
成功并按预期打印0
。 f.bump!
会导致以下NoMethodError
foo.rb:13:in `bump!': undefined method `+' for nil:NilClass (NoMethodError)
from foo.rb:20:in `<main>'
在表达式n
中知道nil
为n += 1
的原因是什么?
使用n = 1 + n
会引发TypeError
(nil cannot be coerced into Fixnum
),因此n
实际上是nil
。
答案 0 :(得分:7)
即使您为n=
定义了Foo
方法,Ruby也不允许您在没有明确接收者的情况下从类中调用它,即{{1 }}
因此,当您撰写self.n=
时,会将其转换为n += 1
。 n = n + 1
没有明确的接收者,所以Ruby创建了一个局部变量n=
(n
)。因此,nil
中的n
引用n + 1
局部变量,为您提供nil
。
仅供参考,您不需要NoMethodError
,除非您希望attr_accessor
可以在课程 之外访问!即便如此,当您编写实例方法时,您应该只使用普通的实例变量n
。
答案 1 :(得分:1)
你的错误在那里:
def bump!
n += 1
end
使用self.n
。或@n
。
当你这样做时:
attr_accessor :n
事实上,你这样做:
def n
@n
end
def n=(value)
@n= value
end
当你执行n += 1
时,使用局部变量(即niL)而不是使用由attr_accessor
创建的两种方法。