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 ofM1
but 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@M1
should behave as if its superclass wasFoo
, so the fact thatFoo.new.foo
does not go through the refinements ofM2
was expected.
However I find the result of 'Foo.new.bar
' strange:refinement:Foo@M1
does not contain the bar method, but its included moduleR1
does. So should not the result be
R1#bar -> Foo#bar
, whithout going through the refinements methods ofM2
?
The spec states "(3) IfC
has included modules, for these modulesM
If a method with nameN
found 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.foo
andBar.new.bar
. According to the spec:
"(7) IfC
has a direct superclass, search the methodN
as specified in "Normal method lookup" from Step 4, whereC
is 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