`instance_eval` 和范围
`instance_eval` and scopes
我有以下代码:
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
运行 中的代码是否与添加的方法在同一范围内?或者,它会在运行之外吗?
其中涉及哪些注意事项和陷阱?
让我们一探究竟!
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.instance_eval
中不需要 self.
。
您的 scope
方法基本上是空操作。当您将一个块传递给产生的方法时,该块将在 current 范围内进行评估。观察:
class A
def self.scope
yield
end
end
A.scope { p self }
# main
由于块中没有产生任何内容,并且 yield
的 return 值也没有做任何事情,块中的任何代码 运行 都将具有相同的效果 运行 在 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
我有以下代码:
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
运行 中的代码是否与添加的方法在同一范围内?或者,它会在运行之外吗?
其中涉及哪些注意事项和陷阱?
让我们一探究竟!
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.instance_eval
中不需要 self.
。
您的 scope
方法基本上是空操作。当您将一个块传递给产生的方法时,该块将在 current 范围内进行评估。观察:
class A
def self.scope
yield
end
end
A.scope { p self }
# main
由于块中没有产生任何内容,并且 yield
的 return 值也没有做任何事情,块中的任何代码 运行 都将具有相同的效果 运行 在 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