2016-08-06 23 views
7

DelegateClass(例:Seller < DelegateClass(Person))での委任の使用方法と、ルビでクラス継承(例:Seller < Person)を使用するタイミングについて、私はGitHubの上でRailsのソースにルビーの上に見ていたDelegateClassとRubyのクラス継承

class Seller < DelegateClass(Person) 
    def sales 
    ... 
    end 
end 

class Seller < Person 
    def sales 
    ... 
    end 
end 

私はかなりの数のuses of DelegateClassを見つけました。

答えて

5

どのアプローチを使用するかについての洞察を提供するのに役立つ2つの違いがあります。あなたが安全に、プリミティブ(例えば文字列)に委任することができますが、常に安全にDelegateClassを使用して、あなたがHashまたはStringまたはFixnumの上に構築している場合は、あなたがより安全だ、彼らから

を継承することはできません

1) (または別の委任者)。理由の詳細については、Steve Klabnik's cautioningが良い場所です)。

2)DelegateClassこれはそれが簡単に、一般的なオブジェクトのインスタンスを受け入れ、それが特定の道に動作させるためになり、より具体的な1

に、より一般的なオブジェクトを「変換」することが容易になります

class Message < DelegateClass(String) 
    def print 
    upcase 
    end 
end 

# […] 

def log(message) 
    message = Message.new(message) unless message.is_a?(Message) 
end 

3)の落とし穴:あなたの実装にDelegateClassサブクラスがnew

の引数として委任クラスのインスタンスを期待します

これは、ライブラリコードに渡しているクラスを「サブクラス化」するのは難しいことがあります。たとえば、これはDelegateClassと箱から出して動作しませんかなり一般的である:私たちのライブラリは、ほとんどのロガーのように動作し、引数なしでインスタンス化することを期待するので

class MyLogger < DelegateClass(ActiveSupport::Logger); end 

Foo::ThirdParty::Library.configure do |c| 
    c.logger = MyLogger # no good 
end 

これは動作しません。これはinitializeを定義し、ActiveSupport::Loggerというインスタンスを作成することで対応できますが、この場合はおそらく正しい解決策ではありません。

0

代理人は、コンテキストに基づいてPersonの異なる動作をモデル化します。例えば同じ人物はあるコンテキストでは売り手、別のコンテキストでは買い手になる可能性があります。継承はより堅牢です:BearTigerAnimalから継承しますが、Animalのインスタンスは、Bearのように振る舞う必要はなく、時にはTigerのように振舞います。 Animalの子孫のインスタンスは、どちらか一方です。