如何动态添加attr_reader

Ler*_*y22 17 ruby

我希望以下代码按预期工作但它给我一个NoMethodError(私有方法`foo'调用#<MyClass ...)

class MyClass
end

my_object = MyClass.new

my_object.instance_variable_set(:@foo, "bar")
MyClass.send("attr_reader", :foo)

puts my_object.foo
Run Code Online (Sandbox Code Playgroud)

问题是我在一个更大的应用程序中使用完全相同的代码并且它的工作方式与我期望的完全相同,但是当我将其简化为最基本的示例时,它会失败.

(我知道还有很多其他方法可以做我在Ruby中做的事情)

Mik*_*wis 10

使用Module#class_eval:

通过这样做,块将您置于MyClass的上下文中,从而允许您调用 attr_reader

ruby-1.9.2-p136 :028 > my_object.instance_variable_set(:@foo, "bar")
 => "bar" 
ruby-1.9.2-p136 :029 > MyClass.class_eval{attr_reader :foo}
 => nil 
ruby-1.9.2-p136 :030 > my_object.foo
 => "bar" 
Run Code Online (Sandbox Code Playgroud)


DVG*_*DVG 5

让我们暂时假设您想要为该类的特定实例创建一个访问器(我假设是这种情况,因为您正在对该实例进行操作。

您可以简单地打开实例的单例类并使用instance_eval添加访问器

class MyClass
end
my_instance = MyClass.new
my_instance.singleton_class.instance_eval { attr_accessor :foo }
my_instance.foo = :bar
my_instance.foo # => :bar
Run Code Online (Sandbox Code Playgroud)


Jos*_*Lee 0

只需强制该方法公开即可:

MyClass.send("public", :foo)
Run Code Online (Sandbox Code Playgroud)

我不知道为什么在某些情况下它是私有的。