Reputation: 1857
look the demo code:
class A
def method_a
puts "this is method_a"
end
end
class B < A
def self.hide_method name
if instance_methods.include? name
@hidden_mthod ||= {}
@hidden_mthod[name] = instance_method name
undef_method name
end
end
def self.invoke_hidden_methods
puts @hidden_mthod.inspect
end
def bound_method name
self.class.class_variable_get(:@hidden_mthod)[name].bind(self)
end
end
b = B.new
b.method_a
B.hide_method :method_a
B.invoke_hidden_methods
b.bound_method :method_a **#error**
b.method_a **#error**
The thing i want to do is rebind special method to the instance.but how can i access @hidden_method which defined in class with instance method?
UPDATED: Thanks,Boris Strandjev, Ur really a nice man. as you above-mentioned, I think the code should be more simplified like this:
def bound_method name
method_body = self.class.instance_variable_get(:@hidden_method)[name]
self.class.send :define_method, name, method_body
end
Upvotes: 0
Views: 307
Reputation: 46963
Change your bound_method
to:
def bound_method name
self.class.instance_variable_get(:@hidden_mthod)[name].bind(self)
end
This is instance variable, not class.
EDIT As per your comment I did not solve your problem. So I had to rust off a lot of ancient ruby knowledge. I found this thread.
And then I changed your method further:
def bound_method name
puts self.class.instance_variable_get(:@hidden_mthod)[name]
metaclass = class << self; self; end
metaclass.send(:define_method, name,
self.class.instance_variable_get(:@hidden_mthod)[name])
end
Basically bind
will allow you to call this method on the instance once like:
self.class.instance_variable_get(:@hidden_mthod)[name].bind(self).call()
But does not add the method to the instance. :define_method
does. Hopefully this will help you.
Upvotes: 2