gpt4 book ai didi

ruby - 为什么你会在 'initialize' 中调用 instance_eval(而不是 class_eval)?

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

  class Observer
def initialize(&block)
instance_eval(&block) if block_given?
end
end

我想知道这里对与“初始化”一起使用的 block 类型做了什么假设。

由于调用了 instance_eval,这意味着该 block 是在 Observer 类的上下文中求值的。

为什么它会这样做,而不是说 class_eval 以及在类的上下文中评估 block 的结果可能是什么?

此外,如何调用它?

最佳答案

首先,你不能这样做:

class Observer
def initialize(&block)
class_eval(&block) if block_given?
end
end

因为 class_eval 没有为 Observer 的实例定义。它在 Module(Class 的派生)中定义。我们稍后会回到 class_eval

使用上述习语的原因通常是允许 block 初始化:

x = Observer.new do
add_event(foo)
some_other_instance_method_on_observer
self.some_attribute = something
end

另外,您可以向类的给定实例添加方法:

foo = Observer.new do
def foo
'foo'
end
end

foo.foo # => "foo"

你可以在没有 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

但这并不能使您能够添加方法。如果您要这样做:

foo = Foo.new do
def foo
'foo'
end
end

foo.foo # => "foo"

这似乎行得通,对吧?但您实际上所做的是将 foo 方法添加到所有内容,因为 self 被设置为“main”对象。相当于简单的在 block 外定义了方法。它们作为实例方法添加到 Object 中,因此它们适用于所有内容。

现在,正如所 promise 的那样,简短地返回到 class_eval。你可以做这样的事情:

class Observer
def initialize(&block)
class.class_eval(&block) if block_given?
end
end

然后你打开了整个类(class):

x = Observer.new { def foo; 'foo'; end }
x.foo # => "foo"
y = Observer.new
y.foo # => "foo"

这通常不是我们想要做的。另外,self 将是类,而不是实例。这使得它对上面演示的 block 初始化毫无用处。

关于ruby - 为什么你会在 'initialize' 中调用 instance_eval(而不是 class_eval)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1422790/

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