Project

General

Profile

Bug #13271

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

Consider the following code: 

 ~~~ruby ~~~ 
 class Foo 
   def foo 
     "Foo#foo" 
   end 
   def bar 
     "Foo#bar" 
   end 
 end 
 class Bar < Foo 
   def foo 
     "Bar#foo -> "+super 
   end 
   def bar 
     "Bar#bar -> "+super 
   end 
 end 

 module R1 
   def foo 
     "R1#foo -> "+super 
   end 
   def bar 
     "R1#bar -> "+super 
   end 
 end 
 module R2 
   def foo 
     "R2#foo -> "+super 
   end 
   def bar 
     "R2#bar -> "+super 
   end 
 end 

 module M2 
   refine Foo do 
     include R2 
     def foo 
       "refinement:Foo@M2#foo -> "+super 
     end 
     def bar 
       "refinement:Foo@M2#bar -> "+super 
     end 
   end 
 end 

 module M1 
   include M2 
   refine Foo do 
     include R1 
     def foo 
       "refinement:Foo@M1#foo -> "+super 
     end 
   end 
 end 

 using M1 
 puts Foo.new.foo #refinement:Foo@M1#foo -> R1#foo -> Foo#foo 
 puts Foo.new.bar #R1#bar -> refinement:Foo@M2#bar -> R2#bar -> Foo#bar 
 puts Bar.new.foo #Bar#foo -> Foo#foo 
 puts Bar.new.bar #Bar#bar -> Foo#bar 
 ~~~ 

 I have several questions about the results. 
 1) As I was expecting, '`using M1`' 'using M1' not only activate the refinements of `M1` M1 but also the refinements of the included module `M2`. M2. 
 In other word it behaves as if I had specified '`using 'using M2; using M1`'. M1'. This is what I was expecting but from reading the spec 
 "(3) Activate refinements in the defined refinement table of `mod`" (({mod}))" it looks like the spec only speak about the refined modules in `M1`. M1. 

 2) As noted in the spec, `refinement:Foo@M1`    refinement:Foo@M1 should behave as if its superclass was `Foo`, Foo, so the fact that `Foo.new.foo` Foo.new.foo does not go through the refinements of `M2` M2 was expected. 
    However I find the result of '`Foo.new.bar`' 'Foo.new.bar' strange: `refinement:Foo@M1` refinement:Foo@M1 does not contain the bar method, but its included module `R1` R1 does. So should not the result be 
    `R1#bar R1#bar -> Foo#bar`, Foo#bar, whithout going through the refinements methods of `M2`? M2? 
    The spec states "(3) If `C` (({C})) has included modules, for these modules `M` {{M}} If a method with name `N` (({N})) found in the method table of `M`, (({M})), return the method." 
    But it does not stipulate what happen if we call super in one of these included method. 

 3) I am also surprised by the behaviour of `Bar.new.foo` Bar.new.foo and `Bar.new.bar`. Bar.new.bar. According to the spec: 
    "(7) If `C` (({C})) has a direct superclass, search the method `N` (({N})) as specified in "Normal ((<"Normal method lookup" lookup">)) from Step 4, where `C` (({C})) is the superclass." 
    and Step 4 start by looking at the activated refinements. 

    
   
    So I was expecting the results to go through `Foo`'s Foo's refinement, so that for instance '`Bar.new.foo`' 'Bar.new.foo' would be 
    `Bar#foo Bar#foo -> refinement:Foo@M1#foo -> R1#foo -> Foo#foo` Foo#foo 

Back