Can you override a method by including a module?

Possible duplicate:
Override the method with others defined in the module

Here is the code:

class Foo def bar puts "Original bar" 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 with the same name is enabled?

+4
source share
3 answers

I do not quite understand your question. What, in fact, do you consider “prevented” here and by whom?

That is how it should work. Module#include mixes in the module as a direct superclass of any class into which it is mixed. M is a superclass of Foo , so Foo#bar redefines M#bar , because the way inheritance works: subclasses redefine superclasses, and not vice versa. Nothing interferes here, of course, you can override Foo#bar in a subclass of Foo .

You can clearly see the pedigree:

 class FooS; end module M; end class Foo < FooS; include M end Foo.ancestors # => [Foo, M, FooS, Object, Kernel, BasicObject] 
+7
source

To rephrase @Jorg's answer:

If you do

 Foo.send(:include,M) Foo.ancestors 

You will return

 [Foo, M, Object, Kernel, BasicObject] 

This means that when the bar call is called, it first sees if Foo#bar , and only if it wasn’t, try looking at M#bar (and then Object , Kernel , BasicObject , and then call method_missing ).

Personally, I do not mind being able to browse M before looking at Foo . I heard that they talked about adding the ability to do this to Ruby 2.0, but that won't help you right now.

+5
source

Your incoming call does not do what you think ... try Foo.send(:extend,M)

-1
source

Source: https://habr.com/ru/post/890202/


All Articles