LeoShi
LeoShi

Reputation: 1857

How can I access class variable in an instance?

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

Answers (1)

Boris Strandjev
Boris Strandjev

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

Related Questions