Hi!
I tried to play with superclass chain and here is what I've
discovered:
The first example, @superclass is changed and method is being found
correctly:
https://gist.github.com/888224
# Step 1. Setting up environment
class Government
def power
"belongs to government"
end
end
module People
def power
"belogs to people"
end
Government.__send__ :include, self
end
government = Government.new
# Step 2. Swapping ancestors by re-setting @superclass
included_module = Government.instance_eval { @superclass }
government.metaclass.instance_eval { @superclass = included_module }
included_module.instance_eval { @superclass = Government }
Government.instance_eval { @superclass = Object }
# Step 3. Testing
puts government.metaclass.superclass_chain.inspect
# => [#<IncludedModule People>, Government, Object, #<IncludedModule
Kernel>] <-------- cool, prepended module is before Class
puts government.power
# => belongs to people <--------- this is definitely right
The second example. Module#direct_superclass is changed.
Module#superclass_chain gives correct result, but wrong method is
being called.
https://gist.github.com/888225
module Rubinius
class PrependedModule < IncludedModule
attr_reader :module
def initialize(mod, superclass)
@module = mod
@superclass = superclass
super(mod)
end
def inspect
"#<PrependedModule #{@module.to_s}>"
end
end
end
class Module
attr_reader :prepended_module # for the sake of simplicity let's
take just one for now
def prepend(mod)
@prepended_module = Rubinius::PrependedModule.new(mod, self)
end
def direct_superclass
if @superclass && @superclass.prepended_module &&
@superclass.prepended_module != self
@superclass.prepended_module
else
@superclass
end
end
end
# -----------------------------------------
class Government
def power
"belongs to government"
end
end
module People
def power
"belogs to people"
end
Government.prepend self
end
puts Government.new.metaclass.superclass_chain.inspect
# => [#<PrependedModule People>, Government, Object, #<IncludedModule
Kernel>] <----- looks good, but...
puts Government.new.power
# => belongs to government <---- ...is this right? ;)
So, I actually have two questions:
1) Is it a bug?
2) If it has been done intentionally, then is there better way
manipulate superclass chain?
Thanks,
Daniel Vartanov.