簡體   English   中英

帶有instance_eval的Ruby塊范圍

[英]Ruby Block Scope with instance_eval

我對Ruby塊和觸發器的理解是它們都是閉包。 現在我已經看到它與instance_eval一起使用,我有點困惑。 什么是魔術醬,在查看裸機時的工作量不足,與使用instance_eval相比,它改變了塊在大多數常見用途下的作用范圍?

以下是您可以在IRB中轉儲以查看我的意思的示例。 我已經包含了proc.call和block yield版本示例。 令人高興的是,他們的行為都是一樣的。

# Testing block/proc and eval
class Example
  def initialize(value)
    # value defined in the instance
    @value = value
  end

  def call_a_proc(proc)
    proc.call self
  end

  def yield_to_block
    yield self
  end
end

# Value defined in the global object
@value = 1
example = Example.new 'a'

# the block/proc that prints @value
proc1 = -> instance { puts @value }

# instance calling/yielding the block/proc that prints @value
proc2 = -> instance { instance.call_a_proc proc1 }
proc3 = -> instance { instance.yield_to_block &proc1 }

# instance_eval of the block that prints @value
proc4 = -> instance { instance.instance_eval &proc1 }

# the block/proc reference @value from the global context, the context in which it was defined (standard closure)
example.call_a_proc proc1
example.yield_to_block &proc1
example.call_a_proc proc2
example.yield_to_block &proc2
example.call_a_proc proc3
example.yield_to_block &proc3

# block/proc has it's context redefined as coming from within the instance.
example.call_a_proc proc4
example.yield_to_block &proc4

我知道這是instance_eval方法的重點,我只是不確定它是如何工作的。

在詞法范圍(主要源文件)中定義@value時,您將在全局解釋器中定義實例變量。 例如:

self #=> main
# "self" here refers to the main interpreter, which is of class Object
self.instance_variable_get(:@value) #=> 1
# "example" is your instance above
example.instance_variable_get(:@value) #=> "a"
# "self" has been changed to refer to "example" using instance_eval
example.instance_eval { self.instance_variable_get(:@value) } #=> "a"
# this syntax is just a shortcut for the line above
example.instance_eval { @value } #=> "a"

使用instance_eval ,您所做的就是用您調用instance_eval的對象替換主解釋器self

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM