我正在做SaaS Stanford课程,试图完成这项任务的第5部分
我很难掌握这个概念,这就是我试图做的事情:
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
Run Code Online (Sandbox Code Playgroud)
我可能会做各种各样的错误,阅读关于元编程的The Book of Ruby章节,我仍然没有得到它,有人能帮我理解这个吗?
我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
Run Code Online (Sandbox Code Playgroud)
我的理解class_eval
是它在运行时类的上下文中计算块- 在我的例子中,在class Foo
.我希望上面的代码运行类似于:
class Foo
attr_count :bar
@count = 0
def bar= (attr_name)
@attr_name = attr_name
@count += 1
end
def bar …
Run Code Online (Sandbox Code Playgroud) 除了工作class_eval
和instance_eval
工作有什么不同def
吗?内部class_eval
块def
定义了类本身的方法(即实例方法),内部instance_eval
def
定义了类的本征类的方法(即类方法).据我所知其他所有功能在这两种情况下(例如相同的工作define_method
,attr_accessor
,class << self; end
,定义常量).这是真的吗?
答案是:def
,undef
并且alias
有不同的背景class_eval
和instance_eval
.
我理解instance_eval
和之间的基本区别class_eval
.我玩的时候发现的东西是奇怪的attr_accessor
.这是一个例子:
A = Class.new
A.class_eval{ attr_accessor :x }
a = A.new
a.x = "x"
a.x
=> "x" # ... expected
A.instance_eval{ attr_accessor :y }
A.y = "y"
=> NoMethodError: undefined method `y=' for A:Class
a.y = "y"
=> "y" # WHATTT?
Run Code Online (Sandbox Code Playgroud)
怎么样:
我知道可以使用class_eval
. 是否可以在class_eval
?的上下文中定义类方法?
我是Ruby的首发.我发现这些都非常相似(在输出中),但我无法理解下面的上下文中的差异.例如,我有一个班级
class Say
def self.hello
puts "hello"
end
end
Run Code Online (Sandbox Code Playgroud)
并且可以像这样扩展
class << Say
def hi
puts "hi"
end
end
Run Code Online (Sandbox Code Playgroud)
也喜欢这个
Say.class_eval do
def self.bye
puts "bye"
end
end
Run Code Online (Sandbox Code Playgroud)
我何时应该使用<<
何时class_eval
?