I have recently been stumped by the following code:
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
succeeds and prints out 0
as expected. f.bump!
causes the following NoMethodError
foo.rb:13:in `bump!': undefined method `+' for nil:NilClass (NoMethodError)
from foo.rb:20:in `<main>'
Any idea why n
is nil
in the expression n += 1
?
Using n = 1 + n
instead raises a TypeError
(nil cannot be coerced into Fixnum
), so n
is in fact nil
.
Even though you've defined an n=
method for Foo
, Ruby won't let you call it from within the class without an explicit receiver i.e. self.n=
So when you write n += 1
, this gets translated into n = n + 1
. n=
doesn't have an explicit receiver so Ruby creates a local variable n
(which is nil
). Thus the n
in n + 1
refers to a nil
local variable, giving you the NoMethodError
.
FYI, you don't need attr_accessor
unless you want n
to be accessible outside of the class! Even then, when you're writing instance methods, you should just use the normal instance variable @n
.
Your error is there :
def bump!
n += 1
end
Use self.n
. Or @n
.
When you do :
attr_accessor :n
In fact you do :
def n
@n
end
def n=(value)
@n= value
end
And when you do n += 1
, you use a local variable (which is niL) instead of using the two methods that were created by the attr_accessor
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With