2014-09-05 46 views
0

嘗試瞭解如何編寫可以在對象上調用的實例方法(通過Object#my_method表示法)。我只能通過將我的對象作爲參數傳遞給方法來獲得所需的結果,但我想了解另一種編寫方法的方法。對象上的Ruby調用方法而不是將方法作爲參數傳遞給方法

class Anagram 
    attr_reader :test_word 

    def initialize(test_word) 
    @test_word = test_word.downcase 
    end 

    def word_stats(word) 
    word.downcase.split("").inject(Hash.new(0)) { |h,v| h[v] += 1; h } 
    end 

    def match(word_list) 
    word_list.delete_if { |word| word.downcase == test_word } 
     word_list.find_all do |word| 
     word_stats(test_word) == word_stats(word) # <= ** THIS LINE ** 
     end 
    end 

end 

我知道我需要改變word_stats方法,但我不知道該如何重寫粗體那行,這樣我可以代替做這樣的事情:

test_word.word_stats == word.word_stats 

這是send的適當位置?有沒有辦法編寫word_stats方法,以便它不需要參數?

謝謝!

回答

1

如果我的理解是正確的,你需要定義word_statsword.class類,這是我想到的是String

class String 
    def word_stats 
    self.downcase.split("").inject(Hash.new(0)) { |h,v| h[v] += 1; h } 
    end 
end 

"My dog has fleas".word_stats 
    #=> {"m"=>1, "y"=>1, " "=>3, "d"=>1, "o"=>1, "g"=>1, 
    # "h=>1, "a"=>2, "s"=>2, "f"=>1, "l"=>1, "e"=>1} 

是你正在做什麼?

+0

這種方法提供的功能就是我正在尋找的功能,但我已經以這種方式警告過元編程(例如,「如果您將方法定義粘貼到核心Ruby類中,那麼您做錯了」除非你正在編寫一個包裝器,一個庫等等) – Jim 2014-09-05 16:05:02

+3

re:「做錯了」:如果你不與別人共享代碼,它可能會覆蓋或導致衝突其他代碼,導致一個真正難以追蹤的錯誤。這個想法是我們可以擴展類,但是我們想要小心地做,並且意識到可能的後果。 – 2014-09-05 16:10:04

+1

Jim,不管你是否想要定義一個新的'String'方法,如果你想寫'word.word_stats',這與'word.send(:word_stats)'相同,這是你唯一的選擇。這隻有在爲類「word.class」定義了實例方法':word_class'時纔有效。順便提一句,這不是元編程;這是多種花園式的方法創作。 – 2014-09-05 16:38:12

1

如果您不希望自己的方法需要參數,那麼請不要在其定義中指定一個參數。在該方法中,如果您需要引用調用該對象的整個對象,則可以通過self關鍵字來完成此操作,但通常您只需訪問其可直接執行的屬性即可。

def word_stats 
    @test_word.downcase.split("").inject(Hash.new(0)) { |h,v| h[v] += 1; h } 
end 
+0

我想知道如何在多個對象上調用word_stats方法。理想情況下,我希望能夠在不止@test_word對象上調用word_stats。我可以在沒有像在你的例子中那樣硬編碼方法定義內特定對象的名字的情況下做到這一點嗎? – Jim 2014-09-05 15:57:55

1

MonkeyPatching沒有錯,特別是如果你有一個小程序,只有Anagram的東西。如果你不在大型或開源項目上工作。猴子補丁!

旁白:查一查紅寶石加細的一個好辦法,限制在Ruby中你的猴子補丁的範圍2.0+

我建議改變你的方法爲布爾和命名它它做什麼,請檢查如果這個詞是一個字謎。

我還包括一個稍微更明顯的算法。

class String 
    def anagram? (check_me) 
    self.downcase.chars.sort == check_me.downcase.chars.sort 
    end 
end 

def match(word_list) 
    word_list.delete_if { |word| word.downcase == test_word.downcase } # might want to downcase test_word as well, unless you know it's downcase already 
    word_list.find_all do |word| 
    word.anagram?(test_word) 
    end 
end 
相關問題