我有以下代码:
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
内的代码是否会在与添加的方法相同的范围内运行?或者,它会在它之外运行吗?
这涉及到什么警告和陷阱?
答案 0 :(得分: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.
中不需要self.instance_eval
。
答案 1 :(得分: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