2015-01-08 11 views
12

私はRubyの洗練された機能を理解しようとしています。私は理解できないシナリオに遭遇しました。私はREPLでこれを行う際に、今絞り込みはインスタンスメソッドにのみ適用されますか?

class Traveller 
    def what_are_you 
    puts "I'm a Backpacker" 
    end 

    def self.preferred_accommodation 
    puts "Hostels" 
    end 
end 


module Refinements 
    module Money 
    def what_are_you 
     puts "I'm a cashed-up hedonist!" 
    end 

    module ClassMethods 
     def preferred_accommodation 
     puts "Expensive Hotels" 
     end 
    end 

    def self.included(base) 
     base.extend ClassMethods 
    end 
    end 

    refine Traveller do 
    include Money 
    end 
end 

は、この例のコードを取る

Traveller.new.what_are_you   # => I'm a Backpacker 
Traveller.preferred_accommodation # => Hostels 

using Refinements 

Traveller.new.what_are_you   # => I'm a cashed-up hedonist! 
Traveller.preferred_accommodation # => Hostels (???) 

はなぜ#what_are_youが洗練されていますが、.preferred_accommodationはないですか?

+1

'Traveller.preferred_accommodation'はクラスメソッドです。 'Traveller.new.preferred_accommodation'はあなたが期待しているものを出力します(基本クラスをインクルードして拡張しているので)。しかし' Traveller'は 'Class'クラスのインスタンスです。 'Traveller.preferred_accommodation'を洗練させたい場合は、class' class_を_refineする必要があります。 – mudasobwa

+1

@ mudasobwa、そうすることはできますが、洗練されたバージョンのメソッドをすべてのクラスで利用できるようにはできませんか?それは、クラスメソッド 'Class'に対してインスタンスメソッドを定義してクラスメソッドを作成するのと同じ問題ではありませんか?それらはすべてのクラスのクラスメソッドになりますか?私は、シングルトンのクラスを洗うこと以上にそれをやっていくことのメリットは分かりません。明らかな欠点もあります。 –

+1

@CarySwoveland確かにあなたは正しいです。私はそれが**クラスの洗練で**行われてはならないと言っています。私がコメントを落とした理由は答えではありません。私は何が起こっているのかを明かそうと思っていましたが、ハウツーレシピを提供したくありませんでした。 – mudasobwa

答えて

15

@MasashiMiyazakiが説明したように、TravellerTravellerのシングルトンクラスの2つのクラスを改良する必要があります。それは実際にあなたのコードかなり簡素化することができます:

module Money 
    refine Traveller do 
    def what_are_you 
     puts "I'm a cashed-up hedonist!" 
    end 
    end 

    refine Traveller.singleton_class do 
    def preferred_accommodation 
     puts "Expensive Hotels" 
    end 
    end 
end 

Traveller.new.what_are_you   #=> I'm a Backpacker 
Traveller.preferred_accommodation #=> Hostels 

using Money 
Traveller.new.what_are_you   #=> I'm a cashed-up hedonist! 
Traveller.preferred_accommodation #=> Expensive Hotels 

また、モジュールに上記の3つの文を置くことによって、二つの方法の洗練されたバージョンは、そのモジュールに限定されています

module M 
    using Money 
    Traveller.new.what_are_you   #=> I'm a cashed-up hedonist! 
    Traveller.preferred_accommodation #=> Expensive Hotels 
end 

Traveller.new.what_are_you   #=> I'm a Backpacker 
Traveller.preferred_accommodation #=> Hostels 
+1

私は "クラスメソッド"は単なる "シングルトンクラスのインスタンスメソッド"であると理解しましたが、何らかの形でその意味を理解できませんでした。 Rubyのオブジェクトモデルをもう少し考えてみると、これは理にかなっています。ありがとう! – andrewdotnich

5

クラスメソッドを上書きするには、singleton_classスコープのrefine Travelerを呼び出す必要があります。 self.includedではなく、詳細モジュールに次のコードを追加すると、期待した結果が得られます。

module Refinements 
    refine Traveller.singleton_class do 
    include Money::ClassMethods 
    end 
end 

この記事(http://timelessrepo.com/refinements-in-ruby)は、詳細を理解するのに役立ちます。

関連する問題