class A
def foo
"A#foo"
end
def singleton_class
class << self
self
end
end
end
a = A.new
puts a.foo #=> A#foo
puts a.singleton_class.ancestors.inspect #=> [A, Object, Kernel]
module X
def foo
"X#foo"
end
end
class A
include X
end
a.extend X
puts a.foo #=> A#foo (and not X#foo!!!!!!!)
puts a.singleton_class.ancestors.inspect #=> [A, X, Object, Kernel] (and not [X, A, X, Object, Kernel])
So remember, you cannot extend or include a class with a module that is already present in the ancestors chain, it will be ignored!





2 comments:
> puts a.foo #=> A#foo (and not X#foo!!!!!!!)
Calling .ancestors should have given you a hint but to quote Programming Ruby "mixed-in modules effectively behave as superclasses". If you changed your 'foo' method definition to:
def foo
super rescue "A#foo"
end
You'll see X#foo as you expect after mixing in X.
This also may help explain why Ruby ignores your a.extend X since X is already mixed in and behaving as a superclass.
That's right.
My mistake comes from implicitely thinking that include or extend where not much than this:
ancestor_chain.add(module)
So it seems they are not as dumb and it's not possible to do weird things like [X, X, X, Object]. They don't just follow orders.
Post a Comment