2013-11-14 62 views
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 

我不知道爲什麼它在前一種情況下不起作用,但在後者中起作用。

+0

你的第二個例子也將拋出錯誤.. –

+0

你的第二個例子會拋出一個錯誤了。 – Nobita

+1

鑑於行號,我懷疑它工作的原因是'abc'已被定義爲更高 –

回答

3

做如下(你錯過@符號)

def pt 
    puts @abc 
end 

那麼,爲什麼PT找不到ABC嗎?

當您使用attr_accessorattr_reader時,您會發生什麼,會發生什麼。請參閱下面的相同。在這種情況下,ruby會首先檢查是否有名稱爲abc的本地變量被創建,但是當它沒有找到它時,檢查是否有一個方法被定義爲名稱abc,通過將消息abc傳遞給selfself.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裸通話只,林心如總是首先檢查它是否是局部變量或沒有。如果在找到的名稱範圍內找不到名稱爲foo的本地變量,則會檢查它是否是方法。見下面一個演示的例子,實現了一個事實:

x = 10 
def x ;11;end 
x # => 10 
+0

當然我知道它可以使用'@'符號。但是我正在測試FALLBACK機制,該機制首先查找本地var'abc',如果沒有找到則應用'self.abc'。 – OneZero

+0

或者OP可能期待'attr_reader:abc'的行爲,並且已經忘記使用它。 –

+1

@OneZero:Ruby中找不到實例變量的「回退機制」。但是,您可以定義一個方法'abc'並讓它返回值。實際上,'attr_reader:abc'和'attr_accessor:abc'會爲你做這件事,所以很多gem允許你創建數據庫類等等。 –

相關問題