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