Reputation: 97
I'm currently going through "The Well Grounded Rubyist 2nd Edition" I'm on page 196 and have been given the following code
class Account
attr_accessor :balance
def initialize(amount=0)
self.balance = amount
end
def +(x)
self.balance += x
end
def -(x)
self.balance -= x
end
def to_s
balance.to_s
end
end
I've used this in and irb session, like so
2.3.3 :001 > require './account.rb'
=> true
2.3.3 :002 > acc = Account.new(20)
=> #<Account:0x007fccb1834ef8 @balance=20>
2.3.3 :003 > balance
NameError: undefined local variable or method `balance' for main:Object
from (irb):3
from /Users/BartJudge/.rvm/rubies/ruby-2.3.3/bin/irb:11:in `<main>'
2.3.3 :004 > acc.balance
=> 20
2.3.3 :005 > acc+=5
=> 25
2.3.3 :006 > acc.balance
NoMethodError: undefined method `balance' for 25:Fixnum
from (irb):6
from /Users/BartJudge/.rvm/rubies/ruby-2.3.3/bin/irb:11:in `<main>'
2.3.3 :007 > acc -= 5
=> 20
2.3.3 :008 > acc.balance
NoMethodError: undefined method `balance' for 20:Fixnum
from (irb):8
from /Users/BartJudge/.rvm/rubies/ruby-2.3.3/bin/irb:11:in `<main>'
2.3.3 :009 >
Line 4 works the way I expected it work acc.balance
However, when I use it again in line 8, i get the following error undefined method `balance' for 20:Fixnum
When I do the following, it works consistently as I expect.
=> true
2.3.3 :002 > acc = Account.new(20)
=> #<Account:0x007f82d1834f18 @balance=20>
2.3.3 :003 > acc.balance
=> 20
2.3.3 :004 > acc.balance
=> 20
2.3.3 :005 > acc.+ (5)
=> 25
2.3.3 :006 > acc.balance
=> 25
2.3.3 :007 > acc.-(10)
=> 15
2.3.3 :008 > acc.balance
=> 15
2.3.3 :009 >
I'm assuming it's something to do with how the methods are being called, but I can't find anything to explain it. Is anyone able to shed some light on the disparity of the results, and why FIXNUM is getting involved. I thought @balance would be an INTEGER.
TIA.
Upvotes: 2
Views: 100
Reputation: 11226
Calling balance
alone will raise NameError
because it's trying to call an object on main which has not been defined. You 'll get the same error if you just call random words like foo
or bar
. Methods must be called on an object.
Max's answer explains part of the problem. However I would suggest you define your class like this to avoid the bug.
class Account
attr_accessor :balance
def initialize(amount=0)
@balance = amount
end
def add(x)
@balance += x
end
def subtract(x)
@balance -= x
end
def to_s
@balance.to_s
end
end
Upvotes: 1
Reputation: 102194
The +=
and -=
assignment operators actually reassign the variable. acc += 1
actually just a shorthand for acc = acc + 1
.
And why FIXNUM is getting involved. I thought @balance would be an INTEGER.
Prior to Ruby 2.4 there where two classes - Fixnum and Bignum that represent integers of different sizes.
Ruby 2.4 replaced them with a unified Integer class.
Upvotes: 1