In the following example, module M
is included in class A
and, afterwards, re-opened to add a submodule MM
, and a method. Then, it is included in class B
:
module M
def foo; "foo" end
end
class A
include M
end
module MM
def baz; "baz" end
end
module M
include MM
def bar; "bar" end
end
class B
include M
end
Instances of both A
and B
can access M
's method regardless of when they were added, but only B
has the method of submodule MM
:
a = A.new
a.foo
a.bar
a.baz # => Error: not defined
b = B.new
b.foo
b.bar
b.baz
I think this is inconsistent behaviour and would like to understand why this happens.
When you include
a module M
into a class C
with superclass S
, this is what happens:
M'
is created whose method table pointer, constant table pointer, instance variable table pointer and class variable table pointer point to M
's method table, constant table, instance variable table and class variable table.M'
s superclass pointer is set to C
's superclass (i.e. S
)C
's superclass pointer is set to M'
This process is repeated recursively for any modules mixed into M
(and modules mixed into modules mixed into M
and so forth).
This way, the linearization of the mixin hierarchy needs to only happen once, when you call include
. The alternative (and this is what you seem to be expecting to happen) would be to perform this pretty expensive process for every single method call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With