Can you override a method by including a module? [duplicate]
Possible Duplicate:
Overriding method by another defined in module
Here's some code:
class Foo
def bar
puts "Original ba开发者_如何学JAVAr"
end
end
module M
def bar
puts "Called M::bar"
end
end
Foo.send(:include,M)
Foo.new.bar
# => Original bar
Does ruby prevent overriding a previously defined method when a method of the same name is "included"?
I don't quite understand your question. What, exactly, do you think is "prevented" here, and by whom?
This is precisely how it is supposed to work. Module#include
mixes in the module as the direct superclass of whatever class it is being mixed into. M
is a superclass of Foo
, so Foo#bar
overrides M#bar
, because that's how inheritance works: subclasses override superclasses, not the other way around. Nothing is being "prevented" here, of course you can still override Foo#bar
in a subclass of Foo
.
You can clearly see the ancestry:
class FooS; end
module M; end
class Foo < FooS; include M end
Foo.ancestors # => [Foo, M, FooS, Object, Kernel, BasicObject]
Rephrasing @Jorg's answer:
If you do
Foo.send(:include,M)
Foo.ancestors
You get back
[Foo, M, Object, Kernel, BasicObject]
That means that when bar
gets called, it looks to see if there's Foo#bar
first, and only if that didn't exist would it try looking at M#bar
(and then Object
, Kernel
, BasicObject
and then calls method_missing
).
Personally speaking, I wouldn't mind the ability for M
to be looked at first, before looking at Foo
. I've heard there's talk of adding to Ruby 2.0 the ability to do this, but that's not going to help you right now.
Your include call doesn't do what you think... try Foo.send(:extend,M)
精彩评论