使用Class.new时访问范围外

ave*_*ave 5 ruby

是否有可能以某种方式访问aClass.new范围内?

a = 5
Class.new{ def b; a end }.new.b
# NameError: undefined local variable or method `a' for #<#<Class:0x007fa8b15e9ca8>:0x007fa8b15e9af0>
# :in `b'
Run Code Online (Sandbox Code Playgroud)

Bro*_*tse 7

即使@MarekLipka答案是正确的 - 改变变量范围总是有风险的.这是有效的,因为每个块都带有它创建的上下文,因此你的局部变量a突然不是本地的 - 它变成了一个'隐藏'的全局:

a = 5
object = Class.new { define_method('b') { a } }.new
object.b #=> 5

a = 4
object.b #=> 4
Run Code Online (Sandbox Code Playgroud)

如果你想通过引用传递不可复制的变量(这实际上与javascript闭包非常相似),这自然很有用,但是在大多数情况下它会引入极难调试的bug:

a = 5
object = Class.new { define_method('b') { a = a + 1 } }.new
object.b
a #=> 6
Run Code Online (Sandbox Code Playgroud)

使用实例变量更加清晰:

a = 5

Class.new do
  def initialize(a)
    @a = a 
  end 

  def b
    @a
  end
end.new(a).b  #=> 5
Run Code Online (Sandbox Code Playgroud)


Mar*_*pka 5

您可以使用define_method代替def关键字并将其传递给关键字(block是闭包,因此它包含对的引用a):

a = 5
Class.new { define_method('b') { a } }.new.b
# => 5
Run Code Online (Sandbox Code Playgroud)