attr_reader

7

7stud 7stud

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?
 
7

7stud ***

From: 7stud 7stud [mailto:[email protected]]
# "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."

Huh? As far as I can tell, no setter methods are created:

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
s.x = 40

--output:--
10
r1test.rb:22: undefined method `x=' for #<Song:0x253c8 @y=20, @x=10,
@z=30> (NoMethodError)

#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?
 
P

Peña, Botp

RnJvbTogN3N0dWQgKioqIFttYWlsdG86ZG9sZ3VuQGV4Y2l0ZS5jb21dIA0KIyBIdWg/ICBBcyBm
YXIgYXMgSSBjYW4gdGVsbCwgbm8gc2V0dGVyIG1ldGhvZHMgYXJlIGNyZWF0ZWQ6DQojIA0KIyBj
bGFzcyBTb25nDQojICAgICBhdHRyX3JlYWRlciA6eCwgOnksIDp6DQoNCnNvcnJ5LCBpIG1pc3Jl
YWQgeW91ciBwb3N0LiAgYXR0cl9yZWFkZXIgb25seSBnaXZlcyBnZXR0ZXJzLg0KDQojIE15IHBy
b2dyYW0gaGFzIG5vIGF0dHJfYWNjZXNzb3IgbGluZSAodGhlIGJvb2sgaGFzbid0IG1lbnRpb25l
ZCANCiMgYXR0cl9hY2Nlc3NvciB5ZXQpLiAgWW91ciBzYXlpbmcgdGhlIGluaXRpYWxpemUgbWV0
aG9kIGluIG15IHByb2dyYW0gDQojIGRvZXNuJ3QgY3JlYXRlIHRoZSBpbnN0YW5jZSB2YXJpYWJs
ZXM/ICANCg0KbXkgZW5nbGlzaCBpcyBwb29yLiBzb3JyeS4gaW5pdGlhbGl6ZSB3aWxsIGNyZWF0
ZSBpdCwgYnV0IGl0J3Mgbm90IHRoZSBvbmx5IHdheS4geW91IGNhbiBjcmVhdGUgeW91ciBvd24g
c2V0dGVycy4NCg0Ka2luZCByZWdhcmRzIC1ib3RwDQoNCg==
 
7

7stud ***

Actually, I think attr_reader does create the instance variables:

class Song
attr_reader :name, :artist, :duration
end

song = Song.new

puts song.name
puts song.artist
puts song.duration

puts song.fake

--output:---
nil
nil
nil
r1test.rb:18: undefined method `fake' for #<Song:0x253c8>
(NoMethodError)
 
7

7stud ***

And this confirms it:

class Song
#attr_reader :name, :artist, :duration
end

song = Song.new

puts song.name
puts song.artist
puts song.duration

puts song.fake

--output:---
r1test.rb:8: undefined method `name' for #<Song:0x25648> (NoMethodError)
 
L

Logan Capaldo

Actually, I think attr_reader does create the instance variables:

class Song
attr_reader :name, :artist, :duration
end

song = Song.new

puts song.name
puts song.artist
puts song.duration

Nope. It's just that an undefined instance variable is treated as
though it were nil. Try this on for size:

puts song.name
puts song.instance_variables
 
7

7stud --

Logan said:
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?
 
7

7stud --

Logan said:
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.
 
S

Sebastian Hungerecker

7stud said:
Logan Capaldo wrote:

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.

HTH,
Sebastian
 
7

7stud --

Sebastian said:
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

Ok. Thanks for the explanation.
 
K

Ken Bloom

And this confirms it:

class Song
#attr_reader :name, :artist, :duration
end

song = Song.new

puts song.name
puts song.artist
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.

--Ken
 
K

Ken Bloom

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.

For most purposes, you'll never notice the difference. There's only one
where you will, and that's when you try to use the defined? keyword on it:

class Foo
def foo
@foo=nil
end
def bar
defined? @foo
end
end

a=Foo.new => #<Foo:0xb7c58b9c>
a.bar => nil
a.foo => nil
a.bar => "instance-variable"

--Ken
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top