2013-12-23 179 views
1
class A 
    attr_accessor :m 

    def n 
    @m + 1 
    end 
end 

a = A.new 
a.m = 4 
p a.n 

我在談論「n」方法中你有@m + 1的代碼。這種代碼易於崩潰,因爲我沒有要求用戶給@m變量賦值?這是一個很好的Ruby編程習慣嗎?

+1

爲什麼你就不能定義一個初始化方法和設置的值@m爲0以避免崩潰的風險? – davidrac

+0

如果我刪除m,它會起作用。但是,如果我做m = m + 1,程序就會崩潰。但是,self.m = m + 1的作品。 :O – daremkd

回答

1

作爲一般規則,屬性在適當的時候應該有默認值,或者值應該傳遞給構造函數。在上述情況下,如果你刪除的a.m = 4線並運行代碼,你會得到這樣的錯誤:

some.rb:5:in `n': undefined method `+' for nil:NilClass (NoMethodError) 
from some.rb:10:in `<main>' 

對於對象,如果屬性有一個默認值,要求他們傳遞通過構造函數進入,如果沒有則失敗。這可以確保無論對象如何實例化,您都將擁有一個合理的默認值。傳遞一個具有暴露值的對象就是代碼中的一個定時炸彈。

+1

除了有一個默認值,另一個選項是引發一個帶有解釋性錯誤信息的異常。 – tokland

0

有兩件事情稍微打擾你的代碼:

  1. 你應該把自己的變量名,而不是他們的實例變量名引用與attr_accessor設定值,這意味着這樣做

    def n 
        m + 1 # and not @m + 1 
    end 
    
  2. 如果一個變量可以是nil,您應該以某種方式防範涉及它的所有涉及nil的操作,即使這意味着引發自定義錯誤,因爲「未定義的NilClass方法+」不是真實的描述性錯誤。這意味着寫這樣的東西會更好

    def n 
        raise StandardError.new("m is not set in instance of A") if m.nil? 
        m + 1 
    end 
    

    如果您要尋找錯誤,這將節省您的時間。此外,您還可以使用默認值m,如果你有一個,而是將其放置在初始化則:

    def initialize 
        super() 
        self.m = 3 #or 
        # self.m ||= 3 This would only set m if it wasn't set by initialization in a superclass 
    end 
    
0

使用二傳手基於依賴​​注入時的屬性是可選的或不需要的建設的對象,當構建對象(或其關鍵功能)需要該屬性時,使用基於構造函數的依賴注入。

在你的情況,如果你的類會做的唯一的事情就是對象調用方法n然後使用構造提供m也可以使用一個二傳手

相關問題