2

我在代码中发现了一个奇怪的错误,它揭示了 ruby​​ 的一个有趣行为。希望有人可以解释为什么它会这样。

我有一个带有实例变量 @foo 的类和一个引用局部范围变量 foo 的方法。我重构了部分方法,不小心留下了对 foo 的引用;该变量不再定义在范围内。它最终指向@foo。更改 foo 会更改 @foo ,反之亦然。

简化版:编辑:添加了 ImOutOfNames。

class ImOutOfNames
    attr_accessor :foo # the culprit!
end

class Bar < ImOutOfNames
    def initialize
        @foo = "that is a tasty burger"
    end

    def bar_method_1
        foo = "Come on Yolanda, whats Fonzie like?"
        bar_method_2
    end

    def bar_method_2
        puts foo
    end
end

bar_method_1 和 bar_method_2 的输出是“那是一个美味的汉堡”。我期待会有一个错误,例如运行上面的代码得到

NameError: undefined local variable or method

我什至请了一位更资深的开发人员来看看,他有些困惑并确认了这种行为。

这是预期的行为,我误解了@variables 的工作原理还是有什么问题?

4

2 回答 2

4

您之前的错误代码可能在attr_accessor 定义中创建了一个访问您的实例变量的方法foo

如果你的代码是这样的,你可以有同样的行为:

class Bar

  attr_accessor :foo

  def initialize
    @foo = "that is a tasty burger"
  end

  def bar_method_1
    foo = "Come on Yolanda, whats Fonzie like?"
    bar_method_2
  end

  def bar_method_2
    puts foo
  end
end

attr_accessor 调用在您的对象中定义了两个方法;

def foo
  @foo
end

def foo=(value)
  @foo = value
end

因此,在您的情况下,当没有定义局部变量时,使用了该方法,但是由于您在此示例中没有调用 attr_accessor,因此您发布了该方法未定义,并且在bar_method_2上没有要使用的局部变量,因此调用失败。

于 2011-08-18T04:33:32.953 回答
0

你有 @foo 实例变量的 attr 访问器吗?这是可能发生这种情况的一种方式。

一般来说,我建议不要对局部范围的变量使用相同的名称,但你可以找出它是否来自某些方法

self.method(:foo)

或者如果它甚至被定义为

defined? foo

使用 ruby​​ 运行时对您有利,肯定会减少某些代码的神秘性和神奇性。

于 2011-08-18T04:33:15.993 回答