# What is the problem with this module function

**URL:** <https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773>\
**Category:** Ruby\
**Created:** [March 22, 2007, 5:52pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773 "2007-03-22T17:52:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 22, 2007, 5:52pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/1 "2007-03-22T17:52:04Z")

</div>

I have a simple class A declared as follows:

class A

def foo  
p “A::foo”  
end

def boo  
p “A::boo”  
end

end

Then I have a simple module ModuleA declared as follows:

module ModuleA  
def module\_a\_foo  
p ‘ModuleA::module\_a\_foo’  
end

def foo  
p ‘ModuleA::foo’  
end  
end

I declare an instance of class A as follows:

a1 = A.new  
a1.methods.sort  
I get all the methods that are declared in class A in my irb console

when I call a1.foo it prints the following as expected  
"A::foo’

Now I reopen class A and include moduleA into this class as follows

class A  
include ModuleA  
end

Now when I type a.methods.sort as expect it displays the methods from  
ModuleA also

When I call ‘a1.module\_a\_foo’ it prints the following as expected.  
“ModuleA::module\_a\_foo”

However now when I call a1.foo I am expecting it to print  
“ModuleA::foo” instead I still get “A::foo”.

I am expecting it to print ModuleA::foo because the method foo in  
ModuleA would overwrite the method foo when I include ModuleA after  
reopening the class A later. Am I missing something here, can anyone  
help me understand this.

Kiran K.

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 22, 2007, 6:05pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/2 "2007-03-22T18:05:21Z")

</div>

On 3/22/07, SunRaySon [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I am expecting it to print ModuleA::foo because the method foo in  
> ModuleA would overwrite the method foo when I include ModuleA after  
> reopening the class A later. Am I missing something here, can anyone  
> help me understand this.
> 
> Kiran K.

Kiran,

You are mistaken about the method lookup precedence in Ruby. The method  
is  
first looked up in the class, then mixin modules, then superclasses,  
etc.

Therefore, the class definition of “foo” is masking the module  
definition of  
“foo”, not the other way around.

- chopper

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 22, 2007, 6:06pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/3 "2007-03-22T18:06:21Z")

</div>

On Mar 22, 10:47 am, SunRaySon [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I am expecting it to print ModuleA::foo because the method foo in  
> ModuleA would overwrite the method foo when I include ModuleA after  
> reopening the class A later. Am I missing something here, can anyone  
> help me understand this.

I suppose the question is “Why were you expecting the module to  
overwrite the instance methods defined in the class?”

Modules included in a class insert themselves after the class itself,  
but before the ancestor of the class:

module Mod  
def foo; “Mod#foo”; end  
end

class A  
def foo; “A#foo”; end  
end

class B \< A  
include Mod  
end

p A.new.foo, B.new.foo  
“A#foo”  
“Mod#foo”

This diagram might help (although perhaps I could improve it a little  
bit to clarify this particular case):

[![](http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png) ](http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png)

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 22, 2007, 8:51pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/4 "2007-03-22T20:51:20Z")

</div>

On Mar 22, 11:31 am, SunRaySon [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Now I am just curious to know if there is any way I can call the  
> module function foo from instance a1.

module M  
def foo; “M#foo #{self.object\_id}”; end  
end

class A  
include M  
def foo; “A#foo #{self.object\_id}”; end  
def mfoo  
M.instance\_method( :foo ).bind( self ).call  
end  
def superfoo  
true\_ancestors = self.class.ancestors - [self.class]  
true\_ancestors.each{ |anc|  
if m = anc.instance\_method( :foo )  
return m.bind( self ).call  
end  
}  
nil  
end  
end

a = A.new  
p a.foo, a.mfoo, a.superfoo

> Also is there any reason why mixin modules are looked upon first  
> before looking at superclasses, again I am mistaken here I was opinion  
> that it would be supreclass and then mixin modules.

Your expectations surprise me. Did you expect that if you had:

class A; end  
class B \< A; end  
class C \< B; end  
class D \< C  
include M  
end  
class E \< D; end  
e = E.new  
e.foo

that Ruby would look for Foo in E, D, C, B, A and _then_ look in M?  
Or did you expect E, D, C, M, B, A?

Ruby looks in E, then D, then M, then C, then B, then A. The reason  
(or at least a reason that makes sense to me) is:

a) Look in yourself before you look any higher.  
b) Modules explicitly included in yourself are more important than  
your superclass.

I think these make sense. Do they make sense when you think about them  
like that?

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 22, 2007, 6:32pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/5 "2007-03-22T18:32:34Z")

</div>

Thanks for the clarification.

Now I am just curious to know if there is any way I can call the  
module function foo from instance a1.

Also is there any reason why mixin modules are looked upon first  
before looking at superclasses, again I am mistaken here I was opinion  
that it would be supreclass and then mixin modules.

Kiran K…

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 23, 2007, 7:27pm UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/6 "2007-03-23T19:27:02Z")

</div>

On 3/22/07, Phrogz [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Ruby looks in E, then D, then M, then C, then B, then A. The reason  
> (or at least a reason that makes sense to me) is:
> 
> a) Look in yourself before you look any higher.  
> b) Modules explicitly included in yourself are more important than  
> your superclass.

This is in general true, however, there’s a quirk,

module M  
def foo  
p ‘M::foo’  
end  
end

class A  
include M  
end

class B \< A  
def foo  
p ‘B::foo’  
end  
end

class C \< B  
include M  
end

Now for the quiz

A.new.foo ==\> “M::foo”  
B.new.foo ==\> “B::foo”  
C.new.foo ==\> ?

Now you might expect that since C explicitly re-included M that it  
should be  
“M::foo”, however instead it’s “B::foo”.

I know why this happens based on what the implementation of module  
inclusion does, I don’t understand WHY it does it that way. It’s just  
the way it is.

For a time, Ruby1.9 allowed re-inclusion of a module by a subclass and  
C.new.foo DID return “M::foo”, but for some reason, the current 1.9  
(or at least the latest version I’ve gotten from SVN) has gone back to  
the old behavior.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![SunRaySon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/22d042/32.png) [@SunRaySon](https://www.ruby-forum.com/u/SunRaySon)\
**Post date:** [March 24, 2007, 4:54am UTC](https://www.ruby-forum.com/t/what-is-the-problem-with-this-module-function/89773/7 "2007-03-24T04:54:18Z")

</div>

Oops! Now I understand how dumb I was, in expecting the superclass  
methods being looked upon first.

Kiran.
