使用Class.new时访问范围外

时间:2015-02-20 12:56:30

标签: ruby

是否有可能以某种方式访问​​Class.new范围内的a

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

3 个答案:

答案 0 :(得分:7)

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

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

a = 4
object.b #=> 4

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

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

使用实例变量更加清晰:

a = 5

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

  def b
    @a
  end
end.new(a).b  #=> 5

答案 1 :(得分:5)

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

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

答案 2 :(得分:-1)

你可以把'a'作为全局变量

$a = 5
Class.new{ def b; $a end }.new.b