为啥尚未定义的局部范围变量引用同名的实例变量?

Posted

技术标签:

【中文标题】为啥尚未定义的局部范围变量引用同名的实例变量?【英文标题】:Why does a locally scoped variable that hasn't been defined reference the instance variable of the same name?为什么尚未定义的局部范围变量引用同名的实例变量? 【发布时间】:2011-10-29 11:06:23 【问题描述】:

我在代码中发现了一个奇怪的错误,它揭示了 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 的输出是“那是一个美味的汉堡”。我原以为会有错误,例如运行上面的代码会得到 ​​p>

NameError: undefined local variable or method

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

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

【问题讨论】:

很奇怪。没有attr_reader :foo 隐藏在某处,是吗?你没有误会什么。如果def foo; @foo end 未定义(显式或通过attr_readerattr_accessor),则foo 不应返回@foo 啊哈!我刚查了一下,确实有一个 attr_accessor :foo. 不错 :) 必须注意那些神奇的方法。将其中一个答案与一个点挂钩:-P 我还没有足够的声望给积分:( 【参考方案1】:

您之前的错误代码可能在 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 上没有可使用的局部变量 所以调用失败。

【讨论】:

有道理,谢谢!我回去检查了一下,它的父类中有一个 attr_accessor。【参考方案2】:

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

一般来说,我建议不要对局部范围的变量使用相同的名称,但您可以通过

了解它是否来自某些方法
self.method(:foo)

或者如果它甚至被定义为

defined? foo

充分利用 ruby​​ 运行时肯定会降低某些代码的神秘性和神奇性。

【讨论】:

以上是关于为啥尚未定义的局部范围变量引用同名的实例变量?的主要内容,如果未能解决你的问题,请参考以下文章

局部变量,实例变量,静态变量

变量类型构造器封装以及 LeetCode 每日一题

全局局部变量,数据的存储类别

为啥方法局部静态变量绑定到类而不是实例?

java中的成员变量、类变量,成员方法、类方法各是啥,怎么区分,

java中类变量、实例变量和局部变量有何区别?