Writable attributes - how does this work?

Hi!

How does this actually work?

from the Pick Axe book:

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 Mektek" <krekna@gmail.com>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
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:

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

How does this actually work?

from the Pick Axe book:

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

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.

Hi!

How does this actually work?

from the Pick Axe book:

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

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.

···

On 5/11/06, Krekna Mektek <krekna@gmail.com> wrote:

Tnx,
Krekna

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

Krekna Mektek wrote:

···

Hi!

How does this actually work?

from the Pick Axe book:

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

--
Posted via http://www.ruby-forum.com/\.

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 Mektek wrote:

···

Hi!

How does this actually work?

from the Pick Axe book:

>

--
Posted via http://www.ruby-forum.com/\.

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

Krekna

···

2006/5/11, corey konrad <0011@hush.com>:

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 Mektek wrote:
> Hi!
>
> How does this actually work?
>
> from the Pick Axe book:
>
> >
>

--
Posted via http://www.ruby-forum.com/\.

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 Fugal

···

On 5/11/06, Philip Hallstrom <ruby@philip.pjkh.com> wrote: