class Observer
def initialize(&block)
instance_eval(&block) if block_given?
end
end
Run Code Online (Sandbox Code Playgroud)
我想知道在这里假设与'initialize'一起使用的块的类型.
由于调用了instance_eval,这意味着在Observer类的上下文中计算块.
为什么它会这样做,而不是比如说class_eval,以及在类的上下文中评估块的结果可能是什么?
另外,如何调用它?
首先,你不能做这样的事情:
class Observer
def initialize(&block)
class_eval(&block) if block_given?
end
end
Run Code Online (Sandbox Code Playgroud)
因为class_eval没有为实例定义Observer.它定义在Module(从中Class下降).我们稍后会回来class_eval.
使用上述习语的原因通常是允许块初始化:
x = Observer.new do
add_event(foo)
some_other_instance_method_on_observer
self.some_attribute = something
end
Run Code Online (Sandbox Code Playgroud)
另外,您可以将方法添加到类的给定实例:
foo = Observer.new do
def foo
'foo'
end
end
foo.foo # => "foo"
Run Code Online (Sandbox Code Playgroud)
没有instance_eval:你可以完成大致相同的事情:
class Foo
def initialize
yield self if block_given?
end
end
foo = Foo.new do |x|
x.add_event(foo)
x.some_other_instance_method_on_observer
x.self.some_attribute = something
end
Run Code Online (Sandbox Code Playgroud)
但这并没有让你能够添加方法.如果你这样做:
foo = Foo.new do
def foo
'foo'
end
end
foo.foo # => "foo"
Run Code Online (Sandbox Code Playgroud)
它似乎工作,对吧?但你实际做的是将foo方法添加到一切,因为self设置为"主"对象.它等同于简单地定义块外的方法.它们作为实例方法添加Object,因此它们可以处理所有事情.
现在,按照承诺,简要回归class_eval.你可以这样做:
class Observer
def initialize(&block)
class.class_eval(&block) if block_given?
end
end
Run Code Online (Sandbox Code Playgroud)
但是你打开了整个班级:
x = Observer.new { def foo; 'foo'; end }
x.foo # => "foo"
y = Observer.new
y.foo # => "foo"
Run Code Online (Sandbox Code Playgroud)
这通常不是我们想要做的.另外,self将是班级,而不是实例.这使得它对于如上所述的块初始化是无用的.
| 归档时间: |
|
| 查看次数: |
710 次 |
| 最近记录: |