instance_eval无法按预期工作

teh*_*wer 0 ruby

我正在尝试使用Russ Olsen在他的书Eloquent Ruby中公开的方法来构建一个简单的DSL.但它对我不起作用.我们考虑以下代码:

class SayHello
  def initialize
    @message = "Hello."
    instance_eval(yield) if yield
  end

  def say_it
    puts @message
  end
end

SayHello.new { say_it }
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

say_hello.rb:12:in `block in <main>': undefined local variable or method `say_it' for main:Object (NameError)
    from say_hello.rb:4:in `initialize'
    from say_hello.rb:12:in `new'
    from say_hello.rb:12:in `<main>'
Run Code Online (Sandbox Code Playgroud)

但是......当你使用instance_eval方法时,self不应该将值赋给调用方法的对象?

提前致谢!

Dav*_*son 5

块运行时,您希望self等于SayHello实例而不是main对象.

我用Google搜索"ruby change self for a block"并找到了一个很好的答案,这让我觉得你应该将代码更改为:

class SayHello
  def initialize(&p)
    @message = "Hello."
    instance_eval(&p) if block_given?
  end

  def say_it
    puts @message
  end
end

SayHello.new { say_it }
Run Code Online (Sandbox Code Playgroud)

  • `&p`将方法的块捕获为proc,然后可以将其传递给`instance_eval`以更改其`self`.`yield`只是传递控制块,只有在块完成后才返回它. (2认同)