0

访问变量时,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

I don't know why it doesn't work in the previous case but works in the latter.

4

1 回答 1

3

Do as below(you missed @ symbol)

def pt
    puts @abc
end

So why pt cannot find abc here?

What you are expecting, will happen, when you will be using attr_accessor or attr_reader. See below for the same. In this case,ruby will first check if there is any local variable is created with the name as abc, but when it doesn't find it,checks if there is a method is defined with name abc,by passing the message abc to self(self.abc). Now attr_reader defines a method def abc; @abc ;end (which is also one of the 2 methods of attr_accessor). Thus no error,you got the output of @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

Remember when there is a bare call like foo only,Ruby will always first check if it is local variable or not. If no local variable is found having name foo in the scope where it is found, then it checks if it is a method. See below one demo example to realize the fact :

x = 10
def x ;11;end
x # => 10
于 2013-11-14T20:50:57.333 回答