开发者

Can you override a method by including a module? [duplicate]

This question already has answers here: Closed 11 years ago.

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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜