# How the Ruby's super work in finding method?

Discussion in 'Ruby' started by Qian Jigui, Nov 20, 2008.

1. ### Qian JiguiGuest

When one method defined in many places, I want to use the super to
invoke them one by one. This is the code:

#########################################
module M
def report( a = 4, b =5)
p "M report begin: a=#{a},b=#{b}"
a = 6
super(a)
p "M report end"
end
end

class B
def report(a=11,b=12)
p "B report 1 begin: a=#{a},b=#{b}"
p "B report 1 end"
end
def report(a=13,b=14)
p "B report 2 begin: a=#{a},b=#{b}"
#super()
p "B report 2 end"
end
end

class C < B
def report( a=8,b=9)
p "C report 1 begin: a=#{a},b=#{b}"
p "C report 1 end"
end
def report( a=7,b=3)
p "C report 2 begin: a =#{a},b=#{b}"
super()
p "C report 2 End"
end
include M
end

class D < C
def report( a = 2, b=1)
p "D report 1 begin: a=#{a},b=#{b}"
super(a,b)
p "D report 1 end"
end
include M
def report(a = -2, b=-1)
p "D report 2 begin: a=#{a},b=#{b}"
super
p "D report 2 end"
end
end

d = D.new
d.report

#########################################
That's the output:

:!ruby testMethodGet.rb
"D report 2 begin: a=-2,b=-1"
"C report 2 begin: a =-2,b=-1"
"M report begin: a=4,b=5"
"B report 2 begin: a=6,b=14"
"B report 2 end"
"M report end"
"C report 2 End"
"D report 2 end"

I find sometimes it will invoke the super class' method first(D->C->M),
but it will invoke the module's method first(C->M->B) too.
I know I include the module in different place in the different classes.
But I don't know the strange working .
Can anyone find the problem?
--
Posted via http://www.ruby-forum.com/.

Qian Jigui, Nov 20, 2008

2. ### Yossef MendelssohnGuest

On Nov 19, 9:23=A0pm, Qian Jigui <> wrote:
> When one method defined in many places, I want to use the super to
> invoke them one by one. This is the code:
>
> #########################################
> module M
> =A0 def report( a =3D 4, b =3D5)
> =A0 =A0 p "M report begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 a =3D 6
> =A0 =A0 super(a)
> =A0 =A0 p "M report end"
> =A0 end
> end
>
> class B
> =A0 def report(a=3D11,b=3D12)
> =A0 =A0 p "B report 1 begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 p "B report 1 end"
> =A0 end
> =A0 def report(a=3D13,b=3D14)
> =A0 =A0 p "B report 2 begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 #super()
> =A0 =A0 p "B report 2 end"
> =A0 end
> end
>
> class C < B
> =A0 def report( a=3D8,b=3D9)
> =A0 =A0 p "C report 1 begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 p "C report 1 end"
> =A0 end
> =A0 def report( a=3D7,b=3D3)
> =A0 =A0 p "C report 2 begin: a =3D#{a},b=3D#{b}"
> =A0 =A0 super()
> =A0 =A0 p "C report 2 End"
> =A0 end
> =A0 include M
> end
>
> class D < C
> =A0 def report( a =3D 2, b=3D1)
> =A0 =A0 p "D report 1 begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 super(a,b)
> =A0 =A0 p "D report 1 end"
> =A0 end
> =A0 include M
> =A0 def report(a =3D -2, b=3D-1)
> =A0 =A0 p "D report 2 begin: a=3D#{a},b=3D#{b}"
> =A0 =A0 super
> =A0 =A0 p "D report 2 end"
> =A0 end
> end
>
> d =3D D.new
> d.report
>
> #########################################
> That's the output:
>
> :!ruby testMethodGet.rb
> "D report 2 begin: a=3D-2,b=3D-1"
> "C report 2 begin: a =3D-2,b=3D-1"
> "M report begin: a=3D4,b=3D5"
> "B report 2 begin: a=3D6,b=3D14"
> "B report 2 end"
> "M report end"
> "C report 2 End"
> "D report 2 end"
>
> I find sometimes it will invoke the super class' method first(D->C->M),
> but it will invoke the module's method first(C->M->B) too.
> I know I include the module in different place in the different classes.
> But I don't know the strange working .
> Can anyone find the problem?

First of all, you can't define a method more than once. That is,
defining it a second time overwrites any previous definition, so if
you're expecting to see B, C, or D report 1, that's not going to
happen.

Second, once a module is part of the ancestor chain, re-including it
doesn't do anything. You have B by itself, then C inherits from B, so
the lookup chain is

C -> B

Then C includes M

C -> M -> B

Then D inherits from C

D -> C -> M -> B

Then D includes M, but M is already present as an ancestor

D -> C -> M -> B

--
-yossef

Yossef Mendelssohn, Nov 20, 2008

3. ### Qian JiguiGuest

Now I know more about the module, super, class and the method finding.
The <RFR> doesn't describe detail.

Yossef Mendelssohn wrote:
> On Nov 19, 9:23ï¿½pm, Qian Jigui <> wrote:
> First of all, you can't define a method more than once. That is,
> defining it a second time overwrites any previous definition, so if
> you're expecting to see B, C, or D report 1, that's not going to
> happen.
>
> Second, once a module is part of the ancestor chain, re-including it
> doesn't do anything. You have B by itself, then C inherits from B, so
> the lookup chain is
>
> C -> B
>
> Then C includes M
>
> C -> M -> B
>
> Then D inherits from C
>
> D -> C -> M -> B
>
> Then D includes M, but M is already present as an ancestor
>
> D -> C -> M -> B

--
Posted via http://www.ruby-forum.com/.

Qian Jigui, Nov 20, 2008