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
···
From: 7stud 7stud [mailto:dolgun@excite.com]
------------------------------------------------------------------------
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?
sorry, i misread your post. attr_reader only gives getters.
# 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?
my english is poor. sorry. initialize will create it, but it's not the only way. you can create your own setters.
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.
--Ken
···
On Sun, 02 Sep 2007 08:53:59 +0900, 7stud *** wrote:
And this confirms it:
class Song #attr_reader :name, :artist, :duration
end
--output:---
r1test.rb:8: undefined method `name' for #<Song:0x25648> (NoMethodError)
--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/
> 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.
On Sun, 02 Sep 2007 13:19:11 +0900, 7stud -- wrote:
Logan Capaldo wrote:
Try this on for size:
puts song.name
puts song.instance_variables
lol. I looked up instance_variables in "Programming Ruby (2d ed)" and it
says:
"Note that simply defining an accessor does not create the corresponding
instance variables."
That statement contradicts the statement I posted earlier on p. 31 of
the same book.
--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology. http://www.iit.edu/~kbloom1/
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