2011-08-18 42 views
2

我在代碼中發現了一個奇怪的錯誤,顯示了一個有趣的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的輸出是「那是一個美味的漢堡」。我原以爲那裏是一個錯誤,例如運行上面的代碼獲取

NameError: undefined local variable or method 

我甚至有一種更高級開發人員來看看,他有點困惑,並確認行爲。

這是一個預期的行爲,我誤解了@variables如何工作或有什麼問題嗎?

+1

很奇怪。沒有一個attr_reader:foo藏在那裏,是嗎?你沒有誤解任何東西。如果'def foo; @foo'沒有被定義(顯式地或者通過'attr_reader'或者'attr_accessor'),'foo'不應該返回'@ foo' aha! – numbers1311407

+0

!我剛查過,確實有一個attr_accessor:foo。 – solipsicle

+0

不錯:)得看那些神奇的方法。用一個觀點鉤住其中一個答案:-P – numbers1311407

回答

4

你以前的越野車在創建一個方法FOO一個訪問到您的實例變量的attr_accessor定義可能的代碼,

可以具有相同的行爲,如果你的代碼是這樣的:

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所以通話失敗。

+0

這很有道理,謝謝! 我回去檢查,其父類中有一個attr_accessor。 – solipsicle

0

你有@troo實例變量的attr訪問器嗎?這是可能發生的一種方式。

我建議不要使用相同的名稱爲本地變量,在一般情況下,但你可以看看它的一些方法來與

self.method(:foo) 

,或者如果它甚至與

定義
defined? foo 

使用ruby運行時對你的優勢絕對減少了某些代碼的神祕性和神奇性。

相關問題