如何在像instance_eval方法的块中更改self?

gao*_*ols 8 ruby metaprogramming self

instance_eval方法在其块中更改self,例如:

class D; end
d = D.new
d.instance_eval do
  puts self  # print something like #<D:0x8a6d9f4>, not 'main'!
end
Run Code Online (Sandbox Code Playgroud)

如果我们定义一个方法selfelf(或任何其他方法(除了instance_eval)接受一个块),当print self时,我们将得到'main',这与instance_eval方法不同.eg:

[1].each do |e|
  puts self  # print 'main'
end
Run Code Online (Sandbox Code Playgroud)

如何定义像instance_eval这样的方法(采用块)?提前致谢.

Ste*_*sen 8

您可以编写一个接受proc参数的方法,然后将其作为proc参数传递给instance_eval.

class Foo
  def bar(&b)
    # Do something here first.
    instance_eval &b
    # Do something else here afterward, call it again, etc.
  end
end
Run Code Online (Sandbox Code Playgroud)

Foo.new.bar {置身}

产量

#<Foo:0x100329f00>
Run Code Online (Sandbox Code Playgroud)

  • 那么,您需要更具体地说明您想要实现的目标。如果您只是想要一个可以接受块的方法,然后在与您的方法相同的上下文中执行它一次或多次,那么就可以做到这一点。如果我不得不猜测,也许您也想将参数传递给块?我知道这是可能的,因为 RSpec 做到了,而这个例子确实没有做到。我应该看一下 RSpec 代码,看看他们是如何做到的。 (2认同)
  • 我仍然不明白为什么重新实现instance_eval比简单地通过调用它来获取它的行为更有用。如果您想了解 Ruby 中的任何内容是如何实现的,apidock.com/ruby 是一个不错的起点。找到您感兴趣的方法(在本例中为http://apidock.com/ruby/Object/instance_eval),然后单击“显示源”。果然,这个方法的实现是用 C 语言实现的,因此您需要下载 Ruby 的源代码来进一步探索。 (2认同)