Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby-使用类_eval定义方法_Ruby_Metaprogramming_Class Eval - Fatal编程技术网

Ruby-使用类_eval定义方法

Ruby-使用类_eval定义方法,ruby,metaprogramming,class-eval,Ruby,Metaprogramming,Class Eval,我在上SaaS斯坦福课程,试着做第五部分 我很难理解这个概念,这就是我试图做的: 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'{def #{attr_name}(a);#{attr_name}_histo

我在上SaaS斯坦福课程,试着做第五部分

我很难理解这个概念,这就是我试图做的:

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'{def #{attr_name}(a);#{attr_name}_history.push(a) ; end;}'
  end
end
我可能做了各种各样的错事,读了《Ruby》中关于元编程的章节,但我仍然不明白,有人能帮我理解吗?

这很有趣

class Class
    def attr_accessor_with_history(attr_name)
        attr_name = attr_name.to_s # make sure it's a string
        attr_reader attr_name
        attr_reader attr_name+"_history"
        class_eval %Q"
            def #{attr_name}=(value)
                if !defined? @#{attr_name}_history
                    @#{attr_name}_history = [@#{attr_name}]
                end
                @#{attr_name} = value
                @#{attr_name}_history << value
            end
        "
    end
end

class Foo
    attr_accessor_with_history :bar
end

class Foo2
    attr_accessor_with_history :bar
    def initialize()
        @bar = 'init'
    end
end

f = Foo.new
f.bar = 1
f.bar = nil
f.bar = '2'
f.bar = [1,nil,'2',:three]
f.bar = :three
puts "First bar:", f.bar.inspect, f.bar_history.inspect
puts "Correct?", f.bar_history == [f.class.new.bar, 1, nil, '2', [1,nil,'2',:three], :three] ? "yes" : "no"
old_bar_history = f.bar_history.inspect

f2 = Foo2.new
f2.bar = 'baz'
f2.bar = f2
puts "\nSecond bar:", f2.bar.inspect, f2.bar_history.inspect
puts "Correct?", f2.bar_history == [f2.class.new.bar, 'baz', f2] ? "yes" : "no"

puts "\nIs the old f.bar intact?", f.bar_history.inspect == old_bar_history ? "yes" : "no"
类
def attr_访问器_和_历史记录(attr_名称)
attr_name=attr_name.to_s#确保它是一个字符串
属性读取器属性名称
属性读取器属性名称+“\u历史”
等级_评估%Q“
def#{attr_name}=(值)
如果!已定义?@#{attr_name}\u历史
@#{attr_name}{attr_name}历史=[@#{attr_name}]
结束
@#{attr_name}=value

@#{attr_name}{u history

关于您所做的事情,实际上您正处于解决方案的尖端。只是
{attr_name}{u history
在您的代码中不存在。您需要创建一个实例变量,如果它不存在,则将其设置为nil。如果它确实存在,则您已经拥有的应该处理推入数组的操作


有几种方法可以做到这一点。一种方法是
如果定义了?@#{attr_name}u history dostuffer

您必须注意,
{attr_name}u history
是一个实例变量,所以使用@before,就像下面类中的@foo一样

def#{attr_name}=value
{attr_name}=
是方法名,
value
是参数,与
def func参数

def #{attr_name}=value
  (!defined? @#{attr_name}_history) ? @#{attr_name}_history = [nil, value] : @#{attr_name}_history << value
end
def#{attr_name}=value

(!defined?@#{attr_name}历史)?@#{attr_name}历史=[nil,value]:@#{attr_name}_历史真的有用吗?如果没有,问题是什么?不确定这个问题是问什么的!看看这是同一个家庭作业问题是的,在我第一次问的时候:解释概念!不要只是给出答案!你伤害的人比帮助的人多。这部分做什么?def#{attr_name}=(价值)。我的意思是,我们在这里真正定义的是什么?请不要重复老问题,除非您有重要的贡献,谢谢。