Writable attributes - how does this work?

Hi!

How does this actually work?

from the Pick Axe book:

irb>
1> class Song
2 > def duration=(new_duration)
3> @duration = new_duration
4> end
5> end
6>
7> song = Song.new(“Bicylops”, “Fleck”, 260)
8> song.duration --> 260
9> song.duration = 257
10> song.duration --> 257

If a method name which is used to set the attribute is called
“duration=”, how come that one can use song.duration = 257?

I mean, does it just work lik this, because the Ruby engine recognizes
the ‘set attribute’ method just because of the = sign after the
“duration” on line number two?

Tnx,
Krekna

Krekna, your understanding is correct:

x = Object.new
=> #Object:0x24870738
x.aa = 10
NoMethodError: undefined method `aa=’ for #Object:0x24870738

note method name reported: ‘aa=’

Sergey

----- Original Message -----
From: “Krekna M.” [email protected]
To: “ruby-talk ML” [email protected]
Sent: Thursday, May 11, 2006 5:12 AM
Subject: Writable attributes - how does this work?

Hi!

How does this actually work?

from the Pick Axe book:

irb>
1> class Song
2 > def duration=(new_duration)
3> @duration = new_duration
4> end
5> end
6>
7> song = Song.new(“Bicylops”, “Fleck”, 260)
8> song.duration → 260
9> song.duration = 257
10> song.duration → 257

If a method name which is used to set the attribute is called
“duration=”, how come that one can use song.duration = 257?

I mean, does it just work lik this, because the Ruby engine recognizes
the ‘set attribute’ method just because of the = sign after the
“duration” on line number two?

Tnx,
Krekna

6>
“duration” on line number two?
You’ll probably get better answers from someone who is smarter than I
am,
but since it’s late and I’m waiting for something to finish, here’s how
I
think about it…

Stop thinking of =, ==, +, *, <=,… as operators. Think of them as
methods.

So, when you see “a = b” that’s really saying call the method “=” on the
object “a” passing as an argument “b”. If you think of it that way then
when you see the below method it will make more sense.

def a= (b)
@a = b
end

So, “a + b” is really:

def a+ (b)
return a + b
end

(yes, I know the return is unecessary, just trying to be clear :slight_smile:

Hope that helps.

On 5/11/06, Krekna M. [email protected] wrote:

4> end
I mean, does it just work lik this, because the Ruby engine recognizes
the ‘set attribute’ method just because of the = sign after the
“duration” on line number two?

Yes! song.duration = 257 calls the duration= method in Song.
It’s as if you wrote song.duration=(257)

You are not actually manipulating Song’s @duration directly.

Its just passing 257 into the duration method via the new_duration
argument and putting it in the @duration attribute variable.

Krekna M. wrote:

Hi!

How does this actually work?

from the Pick Axe book:

irb>
1> class Song
2 > def duration=(new_duration)
3> @duration = new_duration

works basically like

class_name
method_name(argument_name)
@attribute_name = argument_name
end
end

so class_name.method_name = arguments to pass into argument_name

Krekna M. wrote:

Hi!

How does this actually work?

from the Pick Axe book:

irb>

Thanx, it’s clear to me now. Thank you all for the quick answers, each
supplementing each other.

Krekna

2006/5/11, corey konrad [email protected]:

On 5/11/06, Philip H. [email protected] wrote:

Stop thinking of =, ==, +, *, <=,… as operators. Think of them as
methods.

Correct. Usually. As seen below, = sometimes is just an operator.
Others like ! are never methods. And some, like != and +=, are
translated into multiple operators/methods. E.g.

equivalent comparisons, you can’t override != directly

a != b
!(a == b)
!(a.==(b))

equivalent method calls

foo.a += 1
foo.a = foo.a + 1
foo.a=(foo.a + 1)
foo.a=(foo.a.+(1))

equivalent assignments

a += 1
a = a + 1
a = a.+(1)

So, when you see “a = b” that’s really saying call the method “=” on the
object “a” passing as an argument “b”. If you think of it that way then
when you see the below method it will make more sense.

def a= (b)
@a = b
end

Not quite correct.

The = is translated by the parser into a method call only if the left
hand side has an explicit receiver:

equivalent method calls

foo.a = b
foo.a=(b)
foo.send(:“a=”, b)

But if the left hand side has no explicit receiver, the = is simply an
assignment operator to a local (or instance, or class instance)
variable:

direct assignments

a = 5
@a = 5
@@a = 5

So, “a + b” is really:

def a+ (b)
return a + b
end

Also not quite correct. a + b is always a method call, but the name
of the method is just “+”. a is the receiver and b is the argument:

equivalent method calls

a + b
a.+(b)
a.send(:“+”, b)

Even with an explicit receiver on the left hand side, it’s just a
matter of a method call on the value of the left hand side:

equivalent method calls

foo.a + b
foo.a.+(b)

not equivalent

foo.send(:“a+”, b)

As an aside, I don’t think there’s any syntax that would work for
invoking a method named “a+” other than using a direct send.

Jacob F.