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
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
Hi --
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
module Mod1
def hello(options = {})
super(options.merge({:mod1 => true}))
end
module Mod2
def hello(options = {})
super(options.merge({:mod2 => true}))
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
···
On Thu, 20 Jul 2006, Tom Werner wrote:
--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
Ruby for Rails => RUBY FOR RAILS (reviewed on
Slashdot, 7/12/2006!)
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
dblack@wobblini.net => me
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@wobblini.net wrote:
Hi --
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
module Mod1
def hello(options = {})
super(options.merge({:mod1 => true}))
end
module Mod2
def hello(options = {})
super(options.merge({:mod2 => true}))
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
···
On Thu, 20 Jul 2006, Tom Werner wrote:
--
Tom Werner
Helmets to Hardhats
Software Developer
tom@helmetstohardhats.org
www.helmetstohardhats.org