为什么increment_v1和_v3起作用,但是increment_v2和_v4不能起作用(v2返回正确的值,但是不改变@counter
,v4失败,并显示“ NoMethodError(nil:NilClass的未定义方法'+' )“)
class MyClass
attr_accessor :counter
def initialize
@counter = 0
end
def increment_v1
@counter = counter + 1
end
def increment_v2
counter = @counter + 1
end
def increment_v3
@counter += 1
end
def increment_v4
counter += 1
end
end
我希望所有这些方法都具有相同的结果(增加@counter
值并返回增加的数字)。如果我将attr_accessor
替换为attr_reader
和attr_writer
,则会出现相同的错误。我觉得我可能对attr_*
方法有误解。
这是控制台中的样子:
2.6.3 :026 > a = MyClass.new
=> #<MyClass:0x00000000018d7240 @counter=0>
2.6.3 :027 > a.increment_v1
=> 1
2.6.3 :028 > a
=> #<MyClass:0x00000000018d7240 @counter=1>
2.6.3 :029 > a.increment_v2
=> 2
2.6.3 :030 > a
=> #<MyClass:0x00000000018d7240 @counter=1>
2.6.3 :031 > a.increment_v3
=> 2
2.6.3 :032 > a
=> #<MyClass:0x00000000018d7240 @counter=2>
2.6.3 :033 > a.increment_v4
Traceback (most recent call last):
5: from /home/guin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `<main>'
4: from /home/guin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `load'
3: from /home/guin/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
2: from (irb):33
1: from (irb):23:in `increment_v4'
NoMethodError (undefined method `+' for nil:NilClass)
从班级外部运行a.counter += 1
可以正常工作。我上课时是否必须指定self.counter += 1
?为什么?如果使用self.counter = counter + 1
,它甚至可以工作。发生了什么事?
答案 0 :(得分:3)
如所示,您始终可以使用实例变量(@counter
)直接访问属性。但是,您的问题与attr_accessor
生成的getter / setter方法有关。
除非您有同名的局部变量,否则getter方法不需要自身 。设置器方法不同。您总是需要将自己与setter一起使用。
例如:
def test_method
# directly set instance var. this will always work
@counter = 1
# define local variable with same name.
# this does not call the setter because you don't use self
counter = 0
puts counter
# prints 0
# The getter method is never called because you have a local variable
# with the same name.
puts self.counter
# prints 1
# you can force the getter to be called by using self
end
我认为编写方法的惯用方式是:
def increment_v5
self.counter += 1
end
但是您也可以这样写:
def increment_v6
self.counter = counter + 1
# \ calls getter
end
还有许多其他编写方法。