当访问变量时,Ruby中的回退机制首先查找局部变量,如果找不到,则会自动应用self
并查找实例变量。但是,以下代码不起作用:
class My
def init
@abc = "abc"
end
def pt
puts abc
end
end
当我尝试在实例上调用pt
时收到此错误消息:
2.0.0-p247 :009 > my = My.new
=> #<My:0x007f9b5a1b1000>
2.0.0-p247 :010 > my.init
=> "abc"
2.0.0-p247 :011 > my.pt
NameError: undefined local variable or method `abc' for #<My:0x007f9b5a1b1000 @abc="abc">
但是,@abc
作为对象中的实例变量存在:
2.0.0-p247 :012 > my.instance_variables
=> [:@abc]
那么为什么pt
找不到abc
呢?它不应该自动查找实例变量,因为它没有在本地定义,并打印出来吗?
注意:
我知道使用puts @abc
会有效,但这不是我的问题。我的问题是Ruby中的回退机制。此代码有效:
2.0.0-p247 :079 > class My
2.0.0-p247 :080?> def initialize(param)
2.0.0-p247 :081?> @abc = param
2.0.0-p247 :082?> end
2.0.0-p247 :083?>
2.0.0-p247 :084 > def printabc
2.0.0-p247 :085?> puts abc
2.0.0-p247 :086?> end
2.0.0-p247 :087?> end
2.0.0-p247 :089 > My.new("haha").printabc
haha
我不知道为什么它在前一种情况下不起作用,但在后一种情况下起作用。
答案 0 :(得分:3)
执行以下操作(您错过了@
符号)
def pt
puts @abc
end
那么为什么pt在这里找不到abc?
当您使用attr_accessor
或attr_reader
时,您将会发生什么。见下文相同。在这种情况下,ruby将首先检查是否创建了名称为abc
的任何局部变量,但是当它找不到它时,检查是否存在名称为abc
的方法,将消息abc
传递给self
(self.abc
)。现在attr_reader
定义了一个方法def abc; @abc ;end
(它也是attr_accessor
的两种方法之一)。因此没有错误,你得到@abc
的输出。
class My
attr_accessor :abc
def init
@abc = "abc"
end
def pt
puts abc
end
end
my = My.new
my.init # => "abc"
my.pt
# >> abc
请记住,只有像foo
这样的裸呼叫时,Ruby总会首先检查它是否是本地变量。如果在找到它的范围内找不到名称为foo
的局部变量,则会检查它是否为方法。请参阅下面的一个演示示例来实现这一事实:
x = 10
def x ;11;end
x # => 10