On p. 30-31 of “Programming Ruby (2nd ed)”, there is this example:
class Song
attr_reader :name, :artist, :duration
end
and the text says:
“The corresponding instance variables, @name, @artist, and @duration,
will be created for you.”
But I discovered that I still have to define an initialize method to
create objects:
class Song
attr_reader :x, :y, :z
def initialize(x, y, z)
@x = x
@y = y
@z = z
end
end
s = Song.new(10, 20, 30)
puts s.x
So, it seems like initialize is what creates the instance variables.
Or, does attr_reader somehow do its thing before initialize is called?
If so, why is it considered important to know that attr_reader creates
the instance variables instead of initialize?
"The corresponding instance variables, @name, @artist, and @duration,
will be created for you."
that should read: “The corresponding instance variable getter and setter
methods will be created for you.”
irb(main):092:0> system “qri instance_variables”
---------------------------------------------- Object#instance_variables
obj.instance_variables => array
Returns an array of instance variable names for the receiver. Note
that simply defining an accessor does not create the corresponding
instance variable.
class Fred
attr_accessor :a1
def initialize
@iv = 3
end
end
Fred.new.instance_variables #=> ["@iv"]
#So, it seems like initialize is what creates the instance variables.
not really.
irb(main):097:0> class Song2
irb(main):098:1> attr_accessor :x, :y
irb(main):099:1> end
=> nil
note, no initialization there
irb(main):106:0> ix=Song2.new
=> #Song2:0xb7d7efa8
irb(main):107:0> ix.instance_variables
=> []
irb(main):108:0> ix.x=“hi, i am x”
=> “hi, i am x”
note the assignment using the setter method automatically created using
attr_accessor
#So, it seems like initialize is what creates the instance variables.
not really.
irb(main):097:0> class Song2
irb(main):098:1> attr_accessor :x, :y
irb(main):099:1> end
=> nil
note, no initialization there
My program has no attr_accessor line (the book hasn’t mentioned
attr_accessor yet). Your saying the initialize method in my program
doesn’t create the instance variables? What does?
Nope. It’s just that an undefined instance variable is treated as
though it were nil.
Then why isn’t song.fake treated as though it were nil?
song.fake isn’t an instance variable, it’s a method (well actually it’s
not,
it’s nothing, but if it did exists, it’d be a method).
attr_reader :duration creates the method duration, which returns the
instance variable @duration, even if the latter doesn’t exist yet.
song.fake throws an error because there is no method fake, independantly
of whether or not an instance variable @fake exists.
song.instance_variable_get “@fake” would return nil.
attr_reader :duration creates the method duration, which returns the
instance variable @duration, even if the latter doesn’t exist yet.
song.fake throws an error because there is no method fake
On Sun, 02 Sep 2007 08:53:59 +0900, 7stud *** wrote:
puts song.duration
puts song.fake
–output:—
r1test.rb:8: undefined method `name’ for #Song:0x25648 (NoMethodError)
There are two different things going on with attribute readers:
attr_reader :foo creates a method to access the instance variable @foo.
When you get a NoMethodError, because there’s no such method.
Supposing you create an instance variable @bar in some method, such as
initailze, but have no attr_reader for it. You’ll still get a
NoMethodError because attr_reader wasn’t called to create a method for
it.