我正在尝试通过元编程来跟踪每个类变量的历史。我不喜欢问这样的问题,但我花了5个小时才能写出这些问题,从现在开始我不知道如何继续(我是ruby的新手,这是我第一次使用元编程)。
在我看来,当attr_accessor_with_history在一个类中初始化时,它应该执行它所包含的代码。因此,每次这个方法初始化时,由于元编程的优点,每个类都将有自己的方法来解决我所描述的问题。
在我提交的代码中,阅读器被正确初始化,但我不能对class_eval部件中的代码进行同样的说明。我需要澄清代码为什么不工作,以及元编程的一般情况。
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s
attr_reader attr_name
attr_reader attr_name + "_history"
class_eval "%Q{
@#{attr_name}_history=[nil]
def #{attr_name}=(value)
#{attr_name}=value
#{attr_name}_history.push(value)
end
}
"
end
end
class Klass
attr_accessor_with_history :kamil
def initialize(value)
kamil = value
end
end
a = Klass.new(5)
a.kamil = 1
puts "#{a.kamil_history}"发布于 2012-03-04 01:51:48
要在self上调用设置器方法,您需要编写self.foo = bar。如果只是编写foo = bar,它只会创建名为bar的局部变量,而不会调用任何方法。因此,您需要相应地更改第11和23行。
此外,通过在引号中使用%Q{},您的整个eval实际上将仅计算为一个字符串。您应该使用%Q{}或引号,而不是两者都使用。实际上,您可能根本不应该使用字符串,但是可以使用块来调用class_eval,并在块中使用define_method。
发布于 2012-03-04 01:54:43
Saas课程,是吧?您应该知道实例变量应该以@符号开头。例如,在initialize方法中,什么是kamil?如果它是一个实例变量,它应该是@kamil。我还建议您在这方面修改您的class_eval论点。
编辑:
@#{attr_name}_history=[nil]。
我也会把这段代码放到某个方法中,因为用任何方法初始化实例变量都不是很好。
发布于 2012-03-05 17:20:30
您的方法“def attr_accessor_with_history(Attr_name)”中的代码在每次调用此方法时都会被调用。您在编写类Klass attr_accessor_with_history :kamil时在您的类中调用它。
当Ruby处理'attr_accessor_with_history :kamil‘这一行时,它实际上会运行Class.attr_accessor_with_history方法中的代码。class_eval中的字符串被解释为代码,因为它是由您直接编写的。
最后,您的解释代码将如下所示:
克拉斯班..
@kamil_history=nil
def kamil=(value)
kamil=value
kamil_history.push(value)
end看到问题了吗?它必须为@kamil=value,否则它将再次调用方法'kamil=‘,而不是访问实例变量@kamil。
同样,它必须是'@kamil_history.push(..)‘。
你可以在这里找到工作代码:http://maxivak.com/ruby-metaprogramming-and-own-attr_accessor/
https://stackoverflow.com/questions/9548332
复制相似问题