gpt4 book ai didi

ruby - `class_eval` 字符串中的变量范围是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 06:35:51 25 4
gpt4 key购买 nike

我正在使用 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 的理解是,它在运行时类的上下文中 评估 block - 在我的例子中,在 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引起的。我不明白为什么 @countnil:NilClass 作为它的 super ?

(eval):5:in `bar=': undefined method `+' for nil:NilClass (NoMethodError)

另一方面,@selman 给出了一个解决方案,将 @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 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

关于ruby - `class_eval` 字符串中的变量范围是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9466624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com