`class_eval`字符串中的变量范围是什么? [英] What's the variable scope within `class_eval` string?
问题描述
我正在使用class_eval
编写要在当前类的上下文中执行的代码.在下面的代码中,我想添加一个计数器来更改属性值.
I am using class_eval
to write code to be executed under the context of current class. In the following code, I want to add a counter for changes of attribute values.
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
下.我希望上面的代码运行类似于:
My understanding of class_eval
is that it evaluates the block in the context of the runtime class - in my case, under class Foo
. I expect the above code runs similar as:
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
作为其超级键?
However the above code resulted in error saying, the error is caused by @count += 1
. I cannot figure out why @count
has nil:NilClass
as its super?
(eval):5:in `bar=': undefined method `+' for nil:NilClass (NoMethodError)
另一方面,@ selman提供了一种解决方案,可以将@count
分配放入实例方法中,并且可以正常工作.
On the other hand, @selman has given a solution to put @count
assignment within the instance method and it works.
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
如何执行其后续字符串?
Why changes the variable scope works? How does class_eval
execute its following string?
推荐答案
它与class_eval
无关,而与@count
无关.如果在类级别定义此变量,它将是class instance variable
而不是instance variable
.
it is not about class_eval
it is about @count
. if you define this variable at class level it will be a class instance variable
not an 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
这篇关于`class_eval`字符串中的变量范围是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!