2012-04-02 51 views
1

您是否應始終在ruby中創建附件(用於閱讀和/或書寫)?如果你有一個不想在外面重用的類,我不能直接使用實例變量嗎?在ruby中直接使用實例變量是不是很糟糕?

我碰到的一個問題是,在測試中將@instance_vars殘缺掉是有問題的。

+2

你可能會覺得這很有趣:http://talklikeaduck.denhaven2.com/2008/02/15/best-practice-patterns-accessors-and-encapsulation – 2012-04-02 22:10:14

+0

你能舉一個你說什麼的例子嗎? – 2012-04-02 23:17:54

回答

3

當涉及到測試時,實例變量並不重要。您應該測試您的方法,以驗證它們是否會產生正確的結果。

當您爲屬性定義讀取器方法時,會將該屬性公開給世界。如果屬性的值來自實例變量,數據庫,文件,運行時計算或任何其他內容,則無關緊要。人們可以調用該方法來獲取價值。

同樣,當你爲一個屬性定義一個編寫器方法時,你讓每個人都知道他們可以設置它,如果他們需要的話。價值在哪裏並不重要。

只有你的方法定義你的公共API。其他一切都是實現細節。

在您的類定義,肯定是直接訪問實例變量沒有壞處:

@variable = :value 

沒有理由調用方法,如果簡單的分配是你所需要的。當然,有時你需要更復雜的功能。延遲初始化的,例如:

def variable 
    @variable ||= :value 
end 

# ... 

variable.to_s 

如果你的方法是僅供內部使用,你不應該將它包括在公共的API中。將其標記爲私有:

private :variable 

說實話,雖然沒有什麼東西真的被鎖在Ruby中。即使沒有setter方法,人們可以方便地與你的對象篡改,如果他們真的想:

class << (object = Object.new) 
    private 
    def variable; @variable end 
end 

object.variable 
# NoMethodError: private method `variable' called 

# send bypasses access control 
object.send :variable 
# => :value 

object.instance_variables 
# => [:@variable] 
object.instance_variable_get :@variable 
# => :value 

object.instance_variables.each do |variable| 
    object.instance_variable_set variable, nil 
end 
object.instance_variable_get :@variable 
# => nil 
+0

如果一個方法使用了一個實例變量,我需要能夠在測試過程中將它存根:http://stackoverflow.com/questions/9971192/stub-an-instance-variable-using-mocha – m33lky 2012-04-02 21:38:07

+0

@ m33lky,你不' t存根變量,則存根方法。我不熟悉'mocha',但是這裏是如何在'RSpec':'(obj = MyClass.new).stub(:method1).and_return:new_value'中完成的。之後,'obj.method1'將返回':new_value'。 – 2012-04-02 22:03:06

+0

對不起,這是一個不好的例子。我是單位測試方法本身。它有更多的邏輯,但它取決於一個實例變量。 – m33lky 2012-04-02 22:07:59

1

我認爲accessor是更多的東西,可以幫助你有些時候,當你想在設置或執行任務獲取/設置新值之前驗證新變量。如果你確定你不需要它,我認爲最好留在實例變量中。否則,您可以在開始時創建這些代碼,以便在您有大量代碼時您不必在稍後創建它們,並且可以節省大量時間。

1

實例變量是爲了將有問題的實例的上下文中使用。如果您需要與其他對象或其他對象交換數據,則應根據需要使用attr_readerattr_accessor來暴露它們,前提是不要編寫自己的方法來實現此目的。

訪問器方法充當關守,並提供機會讓您驗證外部調用者不會弄亂您的內部狀態。面向對象設計的一個原則是對象承擔篩選輸入的責任。如何處理錯誤的輸入取決於您,無論是忽略它,拋出異常還是在其他事件中記錄錯誤。

如果您沒有處理錯誤的輸入,並因此而崩潰,它最終會成爲您的「錯誤」,您將位於堆棧跟蹤的頂部。先前拒絕錯誤的值會在問題發生的時候顯示出問題,而不是在執行的後面,當時您可能已經失去了分配的來源。

通常,您不希望人們訪問您的數據,除非他們有充分的理由。直接訪問和修改另一個對象的實例變量是不好的形式。

有些語言甚至使得幾乎不可能直接改變對象的內部狀態,但Ruby在這方面相當隨意。儘管如此,僅僅因爲可以做的事情並不意味着它應該。

當您定義訪問器時,是否在該實例的實現中使用它們取決於您。有時直接訪問它們會更方便,因此調用@var而不是self.var,但有些情況下使用訪問器會提供實例變量不支持的其他功能。由於您擁有單一的控制點,因此它還可以讓您的應用程序更輕鬆地重構。

相關問題