2012-12-18 93 views
1

我想了解Ruby Koans的一些內容。在一個教訓,我們做兩個類,如下所示:紅寶石Koans和字符串

class CanNotBeTreatedAsString 
    def to_s 
    "non-string-like" 
    end 
end 

not_like_a_string = CanNotBeTreatedAsString.new 
not_like_a_string == "non-string-like" 

class CanBeTreatedAsString 
    def to_s 
    "string-like" 
    end 

    def to_str 
    to_s 
    end 
end 

like_a_string = CanBeTreatedAsString.new 
like_a_string.to_str == "string-like" 

def acts_like_a_string?(string) 
    string = string.to_str if string.respond_to?(:to_str) 
    string.is_a?(String) 
end 

assert_equal false, acts_like_a_string?(CanNotBeTreatedAsString.new) 
assert_equal true, acts_like_a_string?(CanBeTreatedAsString.new) 

所以兩個階級,最後兩個「斷言」語句是什麼我並不清楚。這兩個類別幾乎完全相同,除了第二個類別只有另一個功能to_str,可撥打to_s。我不明白爲什麼第二個assert語句是真的(因此第二個類可以被視爲一個字符串),只是因爲有第二個函數調用第一個函數。

回答

3

這裏沒有魔法。第二個測試是檢查是否存在to_str方法。這沒有爲CanNotBeTreatedAsString定義,但其,定義爲CanBeTreatedAsString

respond_to?的功能是測試一個方法是否被定義,在Ruby 2.0中它將進一步指示它是否可以被調用。無法調用的受保護方法將不再計數。現在如果respond_to?(:method_name)返回true然後send(:method_name)與任何所需的參數理論上將工作。

第二類可以使用alias :to_str, :to_s以較少的代碼實現相同的結果。

+0

我注意到問題的關鍵是'acts_like_a_string?'的定義方式。我在irb中稍微更改了代碼,因此它會響應':to_s'。 –

2

本課重點在於說明「duck-typing」的原理。基本上,如果它看起來像鴨子,嘎嘎叫鴨子,那麼它就是一隻鴨子。在這種情況下,決定某個字符串是否是唯一的因素(或者說,就像是一個字符串一樣)是如果它對to_str方法做出響應的。

嘗試在交互式ruby(irb)會話中運行此代碼並試驗這兩個類。您會發現每個班級的實例將會響應to_s,但只有CanBeTreatedAsString會迴應to_str。這意味着,就Ruby而言,CanBeTreatedAsString與其他任何響應to_str的字符串一樣多。