Geo*_*Geo 13 ruby eval metaprogramming
我正在尝试做一个instance_eval跟随attr_accessor内部initialize,我继续得到这个:``initialize':未定义的方法'attr_accessor'.为什么这不起作用?
代码看起来像这样:
class MyClass
def initialize(*args)
instance_eval "attr_accessor :#{sym}"
end
end
Run Code Online (Sandbox Code Playgroud)
sep*_*p2k 20
您无法在实例上调用attr_accessor,因为attr_accessor未定义为MyClass的实例方法.它仅适用于模块和类.我怀疑你想在实例的元类上调用attr_accessor,如下所示:
class MyClass
def initialize(varname)
class <<self
self
end.class_eval do
attr_accessor varname
end
end
end
o1 = MyClass.new(:foo)
o2 = MyClass.new(:bar)
o1.foo = "foo" # works
o2.bar = "bar" # works
o2.foo = "baz" # does not work
Run Code Online (Sandbox Code Playgroud)
更清晰的实现(注意:这将为该类的所有实例添加访问器,而不仅仅是单个实例,请参阅下面的注释):
class MyClass
def initialize(varname)
self.class.send(:attr_accessor, varname)
end
end
Run Code Online (Sandbox Code Playgroud)
Rob d'Apice 几乎是对的.你只需要写:
self.singleton_class.send(:attr_accessor, varname)
Run Code Online (Sandbox Code Playgroud)
要么
self.singleton_class.class_eval "attr_accessor :#{varname}"
Run Code Online (Sandbox Code Playgroud)
或者我最喜欢的变种
self.singleton_class.class_exec do attr_accessor varname end
Run Code Online (Sandbox Code Playgroud)
假设值varname是一个符号