Bug #13271
closedClarifications on refinement spec
Description
Consider the following code:
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.
-
As I was expecting, '
using M1' not only activate the refinements ofM1but also the refinements of the included moduleM2.
In other word it behaves as if I had specified 'using M2; using M1'. This is what I was expecting but from reading the spec
"(3) Activate refinements in the defined refinement table ofmod" it looks like the spec only speak about the refined modules inM1. -
As noted in the spec,
refinement:Foo@M1should behave as if its superclass wasFoo, so the fact thatFoo.new.foodoes not go through the refinements ofM2was expected.
However I find the result of 'Foo.new.bar' strange:refinement:Foo@M1does not contain the bar method, but its included moduleR1does. So should not the result be
R1#bar -> Foo#bar, whithout going through the refinements methods ofM2?
The spec states "(3) IfChas included modules, for these modulesMIf a method with nameNfound in the method table ofM, return the method."
But it does not stipulate what happen if we call super in one of these included method. -
I am also surprised by the behaviour of
Bar.new.fooandBar.new.bar. According to the spec:
"(7) IfChas a direct superclass, search the methodNas specified in "Normal method lookup" from Step 4, whereCis the superclass."
and Step 4 start by looking at the activated refinements.So I was expecting the results to go through
Foo's refinement, so that for instance 'Bar.new.foo' would be
Bar#foo -> refinement:Foo@M1#foo -> R1#foo -> Foo#foo