Forum: Ruby Writable attributes - how does this work?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C9030f7616a7da0dd3e7bf4987f46f07?d=identicon&s=25 Krekna Mektek (Guest)
on 2006-05-11 11:13
(Received via mailing list)
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
Ced5fff44ff8929fc974012ea108b284?d=identicon&s=25 Sergey Volkov (rf-vsv)
on 2006-05-11 11:25
(Received via mailing list)
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:

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
48124635945b45221ba12a26371f9e3e?d=identicon&s=25 Philip Hallstrom (Guest)
on 2006-05-11 11:28
(Received via mailing list)
> 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 :)

Hope that helps.
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-11 11:31
(Received via mailing list)
On 5/11/06, Krekna Mektek <krekna@gmail.com> 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.
139a2a2f6b330cc59a8dc6384bbf8837?d=identicon&s=25 Corey Konrad (ckonrad)
on 2006-05-11 11:44
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:
>
> irb>
> 1>  class Song
> 2 >  def duration=(new_duration)
> 3>     @duration = new_duration
>
139a2a2f6b330cc59a8dc6384bbf8837?d=identicon&s=25 Corey Konrad (ckonrad)
on 2006-05-11 11:58
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:
>
> irb>
>
C9030f7616a7da0dd3e7bf4987f46f07?d=identicon&s=25 Krekna Mektek (Guest)
on 2006-05-11 14:16
(Received via mailing list)
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>:
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-05-11 17:54
(Received via mailing list)
On 5/11/06, Philip Hallstrom <ruby@philip.pjkh.com> 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 Fugal
This topic is locked and can not be replied to.