为啥尚未定义的局部范围变量引用同名的实例变量?
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_reader
或attr_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 运行时肯定会降低某些代码的神秘性和神奇性。
【讨论】:
以上是关于为啥尚未定义的局部范围变量引用同名的实例变量?的主要内容,如果未能解决你的问题,请参考以下文章