2012-02-16 73 views
35

我對ruby(我實際上是c#dev)非常陌生,所以這個問題可能是一個noob的問題。 我有一個像下面這樣的類,我使用實例變量(數組)來避免使用大量的方法參數。在類方法中使用實例變量 - Ruby

它按我的預期工作,但這是一個很好的做法嗎? 其實我不會期望這個工作,但我猜測類方法不能用作其他語言的靜態方法,所以我想知道這是否是一種好的做法,或者如果我可能面臨的問題,如將這些變量作爲類變量搞亂一切。

class DummyClass 
    def self.dummy_method1 
    @arr = [] 
    # Play with that array 
    end 

    def self.dummy_method2 
    # use @arr for something else 
    end 
end 

回答

58

Ruby中的類實例變量的工作原理是Ruby類實例本身(類Class的實例)。通過檢查DummyClass.class來嘗試自己。 Ruby中的C#意義上沒有「靜態方法」,因爲每個方法都在某個實例上定義(或繼承)並在某個實例上調用。因此,他們可以訪問被調用者可用的任何實例變量。

由於DummyClass是一個實例,它可以擁有自己的實例變量。你甚至可以訪問那些實例變量,只要你有一個類的引用(應該總是因爲類名是常量)。在任何時候,您都可以調用::DummyClass.instance_variable_get(:@arr)並獲取該實例變量的當前值。

至於是否是件好事,取決於方法

如果@arr邏輯上是實例/類DummyClass的「狀態」,則將其存儲在實例變量中。如果@arr僅作爲可操作的快捷方式在dummy_method2中使用,則將其作爲參數傳遞。爲了給出一個使用實例變量方法的例子,請考慮Rails中的ActiveRecord。它允許你這樣做:

u = User.new 
u.name = "foobar" 
u.save 

這裏,分配給用戶的名稱是合法用戶的數據。如果在撥打#save之前,有人要問「此時用戶的姓名是什麼」,則可以回答「foobar」。如果你深入挖掘內部元素(你會深入挖掘很多元編程,你會發現他們使用實例變量)。

我用過的示例包含兩個單獨的公共調用。要查看實例變量仍在使用中的情況,請查看#update_attributes的ActiveRecord實現。方法體僅僅是load(attributes, false) && save。爲什麼#save不會傳遞任何參數(如新的name),即使它將保存在UPDATE users SET name='foobar' WHERE id=1;之類的內容中?這是因爲名稱之類的東西是屬於實例的信息。

相反,我們可以看一下實例變量無法使用的情況。查看#link_to_if的實現,該方法接受布爾型ish參數(通常是源代碼中的表達式)以及#link_to通常接受的參數,例如鏈接到的URL。當布爾條件爲truthy時,它需要將其餘參數傳遞給#link_to並調用它。在這裏分配實例變量沒有多大意義,因爲您不會說這裏的調用上下文(渲染器)在實例中包含該信息。渲染器本身沒有「鏈接到的URL」,因此它不應該被隱藏在實例變量中。

+1

非常感謝你對這個很好的解釋,特別是關於這是否是一種好的做法。 – tackleberry 2012-02-16 13:21:17

16

這些都是類的實例變量,並在紅寶石完全合法的事情:類對象太(類的實例),因此擁有實例變量。

要注意的一件事是,每個子類都有自己的一組類實例變量(畢竟這些是不同的對象):如果子類DummyClass,子類的類方法將無法看到@arr

類變量(@@foo)當然是另一種方式:整個類層次共享相同的類變量。

+0

嗯這是不同的東西。所以,只要我不會繼承一個新的類,那就不用擔心了。這是個好消息,謝謝! – tackleberry 2012-02-16 12:58:38