[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

extend weirdness?

Ian White

12/21/2006 3:20:00 PM

Hi Group,

This code:
module Foo
def self.included(base)
base.class_eval <<-end_eval
def self.meth
"Foo"
end
end_eval
end
end

module Bar
def self.included(base)
base.class_eval do
extend ClassMethods
end
end

module ClassMethods
def meth
"Bar"
end
end
end

class A
include Foo
include Bar
end

puts A.meth

produces:
Foo

whereas I would expect it to produce "Bar"

Can anyone explain what's going on here? i.e. Why the latter extend
with Bar doesn't over-write the class method introduced by Foo

Cheers,
Ian White

4 Answers

Ian White

12/21/2006 3:34:00 PM

0

The previous post is using a rails-style idiom, which is unnecessarily
complex for the problem at hand.
Here's a simpler example to the same effect:

module Foo
def self.included(base)
class<<base
def meth
"Foo"
end
end
end
end

module Bar
def meth
"Bar"
end
end

class A
include Foo
extend Bar
end

puts A.meth

Which produces "Foo"

There's a workaround (remove the method by hand):

module Bar
def self.extended(base)
class<<base
remove_method :meth
end
end
end

But this workaround does what I'd expect Ruby to do (overwrite any
existing methods when extending)

I'm confused - is this expected behaviour?

Cheers,
Ian

ps.

$ ruby --version
ruby 1.8.5 (2006-08-25) [powerpc-darwin8.7.0]

dblack

12/21/2006 3:58:00 PM

0

Ian White

12/21/2006 4:24:00 PM

0

Thanks David for that very clear explanation, I am no longer confused.

Cheers,
Ian

Vincent Fourmond

12/21/2006 5:00:00 PM

0

Ian White wrote:
> Hi Group,
>
> This code:
> module Foo
> def self.included(base)
> base.class_eval <<-end_eval
> def self.meth
> "Foo"
> end
> end_eval
> end
> end
>
> module Bar
> def self.included(base)
> base.class_eval do
> extend ClassMethods
> end
> end
>
> module ClassMethods
> def meth
> "Bar"
> end
> end
> end
>
> class A
> include Foo
> include Bar
> end
>
> puts A.meth
>
> produces:
> Foo
>
> whereas I would expect it to produce "Bar"
>
> Can anyone explain what's going on here? i.e. Why the latter extend
> with Bar doesn't over-write the class method introduced by Foo

The answer is simple: extend doesn't overwrite methods, it just
includes the module for the singleton object. As there is already a
singleton method 'meth' defined in the singleton object A, this method
is used systematically in method calls.

Does that explain your result ? For information, extend is

rb_extend_object(obj, module)
VALUE obj, module;
{
rb_include_module(rb_singleton_class(obj), module);
}

It is basically like

class << self
include Something
end

Cheers,

Vince

--
Vincent Fourmond, PhD student
http://vincent.fourmon...