2

我有以下代码:

class A
  def self.scope
    yield
  end
  def self.method_added method
    self.instance_eval %{
      # do something involving the added method 
    }
  end
end

class B < A
  scope do 
    def foo
    end
  end
end

method_added钩子被触发时,里面的代码会instance_eval在与添加的方法相同的范围内运行吗?或者,它会在它之外运行吗?

这其中有哪些注意事项和陷阱?

4

2 回答 2

1

您的scope方法基本上是无操作的。当您将块传递给产生的方法时,该块将在当前范围内进行评估。观察:

class A
  def self.scope
    yield
  end
end

A.scope { p self }
# main

由于该块没有产生任何内容,并且没有对 的返回值做任何事情,因此yield在该块中运行的任何代码都将在该块外运行具有相同的效果scope

然而,情况并非如此instance_eval。当instance_eval运行一个块时,self块内被设置为接收者(而不是self块范围内的任何内容)。像这样:

class A
end

A.instance_eval { p self }
# A

但请注意,这意味着这self.instance_eval { ... }也是一个花哨的无操作,因为您将块更改为块外self的相同self

所以你的代码相当于这个:

class A
  def self.method_added method
    # do something involving the added method 
  end
end

class B < A
  def foo
  end
end
于 2015-01-29T19:32:20.643 回答
1

让我们来了解一下!

class A
  def self.scope
    yield
  end
  def self.method_added method
    puts "In method_added, method = #{method}, self = #{self}" 
    instance_eval 'puts "In instance_eval, method = #{method}, self = #{self}"'
  end
end

class B < A
  scope do
    puts "In scope's block, self = #{self}" 
    def foo
    end
  end
end

  # In scope's block, self = B
  # In method_added, method = foo, self = B
  # In instance_eval, method = foo, self = B

请注意,您不需要self.in self.instance_eval

于 2015-01-29T19:16:43.367 回答