[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Object#extend inner workings

Tom Werner

7/19/2006 11:08:00 PM

I've got a question regarding the inner workings of extend. Consider the
following code that uses Object#extend twice:

class Klass
def hello(options = {})
p options
end
end

module Mod1
def hello(options = {})
super(options.merge({:mod1 => true}))
end
end

module Mod2
def hello(options = {})
super(options.merge({:mod2 => true}))
end
end

k = Klass.new
k.hello #=> {}

k.extend(Mod1)
k.hello #=> {:mod1=>true}

k.extend(Mod2)
k.hello #=> {:mod2=>true, :mod1=>true}

I was a bit surprised that the second extend didn't clobber the first.
How is this handled by the Ruby interpreter? Is it creating more than
one eigenclass?

Tom

--
Tom Werner
Helmets to Hardhats
Software Developer
tom@helmetstohardhats.org
www.helmetstohardhats.org


5 Answers

Justin Collins

7/19/2006 11:17:00 PM

0

Tom Werner wrote:
> I've got a question regarding the inner workings of extend. Consider
> the following code that uses Object#extend twice:
>
> class Klass
> def hello(options = {})
> p options
> end
> end
>
> module Mod1
> def hello(options = {})
> super(options.merge({:mod1 => true}))
> end
> end
>
> module Mod2
> def hello(options = {})
> super(options.merge({:mod2 => true}))
> end
> end
>
> k = Klass.new
> k.hello #=> {}
>
> k.extend(Mod1)
> k.hello #=> {:mod1=>true}
>
> k.extend(Mod2)
> k.hello #=> {:mod2=>true, :mod1=>true}
>
> I was a bit surprised that the second extend didn't clobber the first.
> How is this handled by the Ruby interpreter? Is it creating more than
> one eigenclass?
>
> Tom
>

As I understand it, Ruby adds another "transparent" superclass each time
you use extend or include. You can of course do that as many times as
you want to get all kinds of mix-in functionality. There are some nice
diagrams in the Pickaxe book that show this (I don't have it with me at
the moment).


-Justin

Tom Werner

7/19/2006 11:29:00 PM

0

Justin Collins wrote:
> Tom Werner wrote:
>> I've got a question regarding the inner workings of extend. Consider
>> the following code that uses Object#extend twice:
>>
>> class Klass
>> def hello(options = {})
>> p options
>> end
>> end
>>
>> module Mod1
>> def hello(options = {})
>> super(options.merge({:mod1 => true}))
>> end
>> end
>>
>> module Mod2
>> def hello(options = {})
>> super(options.merge({:mod2 => true}))
>> end
>> end
>>
>> k = Klass.new
>> k.hello #=> {}
>>
>> k.extend(Mod1)
>> k.hello #=> {:mod1=>true}
>>
>> k.extend(Mod2)
>> k.hello #=> {:mod2=>true, :mod1=>true}
>>
>> I was a bit surprised that the second extend didn't clobber the
>> first. How is this handled by the Ruby interpreter? Is it creating
>> more than one eigenclass?
>>
>> Tom
>>
>
> As I understand it, Ruby adds another "transparent" superclass each
> time you use extend or include. You can of course do that as many
> times as you want to get all kinds of mix-in functionality. There are
> some nice diagrams in the Pickaxe book that show this (I don't have it
> with me at the moment).
>
>
> -Justin
>
>
But the behavior of the modules is that of a subclass (being able to
call super to call a method in Klass). If I were to use include inside
the class definition, then I would indeed get superclass behavior.

Tom

--
Tom Werner
Helmets to Hardhats
Software Developer
tom@helmetstohardhats.org
www.helmetstohardhats.org


dblack

7/19/2006 11:34:00 PM

0

Justin Collins

7/19/2006 11:35:00 PM

0

Tom Werner wrote:
> Justin Collins wrote:
>> Tom Werner wrote:
>>> I've got a question regarding the inner workings of extend. Consider
>>> the following code that uses Object#extend twice:
>>>
>>> class Klass
>>> def hello(options = {})
>>> p options
>>> end
>>> end
>>>
>>> module Mod1
>>> def hello(options = {})
>>> super(options.merge({:mod1 => true}))
>>> end
>>> end
>>>
>>> module Mod2
>>> def hello(options = {})
>>> super(options.merge({:mod2 => true}))
>>> end
>>> end
>>>
>>> k = Klass.new
>>> k.hello #=> {}
>>>
>>> k.extend(Mod1)
>>> k.hello #=> {:mod1=>true}
>>>
>>> k.extend(Mod2)
>>> k.hello #=> {:mod2=>true, :mod1=>true}
>>>
>>> I was a bit surprised that the second extend didn't clobber the
>>> first. How is this handled by the Ruby interpreter? Is it creating
>>> more than one eigenclass?
>>>
>>> Tom
>>>
>>
>> As I understand it, Ruby adds another "transparent" superclass each
>> time you use extend or include. You can of course do that as many
>> times as you want to get all kinds of mix-in functionality. There are
>> some nice diagrams in the Pickaxe book that show this (I don't have
>> it with me at the moment).
>>
>>
>> -Justin
>>
>>
> But the behavior of the modules is that of a subclass (being able to
> call super to call a method in Klass). If I were to use include inside
> the class definition, then I would indeed get superclass behavior.
>
> Tom
>

Oh, right, nevermind.

-Justin

Tom Werner

7/19/2006 11:38:00 PM

0

dblack@wobblini.net wrote:
> Hi --
>
> On Thu, 20 Jul 2006, Tom Werner wrote:
>
>> I've got a question regarding the inner workings of extend. Consider
>> the following code that uses Object#extend twice:
>>
>> class Klass
>> def hello(options = {})
>> p options
>> end
>> end
>>
>> module Mod1
>> def hello(options = {})
>> super(options.merge({:mod1 => true}))
>> end
>> end
>>
>> module Mod2
>> def hello(options = {})
>> super(options.merge({:mod2 => true}))
>> end
>> end
>>
>> k = Klass.new
>> k.hello #=> {}
>>
>> k.extend(Mod1)
>> k.hello #=> {:mod1=>true}
>>
>> k.extend(Mod2)
>> k.hello #=> {:mod2=>true, :mod1=>true}
>>
>> I was a bit surprised that the second extend didn't clobber the
>> first. How is this handled by the Ruby interpreter? Is it creating
>> more than one eigenclass?
>
> No, it's just inserting the modules along the method lookup chain.
> You can examine it like this:
>
> class << k
> p ancestors
> end
>
> which gives you:
>
> [Mod2, Mod1, Klass, Object, Kernel]
>
> So Mod2 comes before Mod1, but the class (k's singleton class) still
> has Mod1 mixed in.
>
>
> David
>
Ah! Have I said I love Ruby today?

Thanks David.

Tom

--
Tom Werner
Helmets to Hardhats
Software Developer
tom@helmetstohardhats.org
www.helmetstohardhats.org