`class_eval`字符串中的变量范围是什么?
我正在使用class_eval
编写要在当前类的上下文中执行的代码。 在以下代码中,我想为属性值的更改添加计数器。
class Class def attr_count(attr_name) attr_name = attr_name.to_s attr_reader attr_name # create the attribute's getter class_eval %Q{ @count = 0 def #{attr_name}= (attr_name) @attr_name = attr_name @count += 1 end def #{attr_name} @attr_name end } end end class Foo attr_count :bar end f = Foo.new f.bar = 1
我对class_eval
理解是它在运行时类的上下文中计算块 – 在我的例子中,在class Foo
。 我希望上面的代码运行类似于 :
class Foo attr_count :bar @count = 0 def bar= (attr_name) @attr_name = attr_name @count += 1 end def bar @attr_name end end
但是上面的代码导致错误说,错误是由@count += 1
引起的。 我无法弄清楚为什么@count
nil:NilClass
为超级?
(eval):5:in `bar=': undefined method `+' for nil:NilClass (NoMethodError)
另一方面,@ serman给出了一个解决方案,可以在实例方法中放置@count
赋值,并且它可以工作。
class Class def attr_count(attr_name) #... class_eval %Q{ def #{attr_name}= (attr_name) @attr_name = attr_name if @count @count += 1 else @count = 1 end end #... } end end
为什么更改变量范围有效? class_eval
如何执行以下字符串?
它与class_eval
它与@count
有关。 如果在类级别定义此变量,它将是class instance variable
而不是instance variable
。
class Class def attr_count(attr_name) attr_name = attr_name.to_s attr_reader attr_name # create the attribute's getter class_eval %Q{ def #{attr_name}= (attr_name) @attr_name = attr_name if @count @count += 1 else @count = 1 end end def #{attr_name} @attr_name end } end end class Foo attr_count :bar end f = Foo.new f.bar = 1