8

ハッシュのように動作するクラスが必要ですが、必ずしもすべてのハッシュ メソッドで使用できるわけではありません。Hash のようなコア クラスをサブクラス化するのは得策ではないことを読みました。それが真実であるかどうかにかかわらず、この種のことを行うためのベストプラクティスは何ですか?

# (a) subclass Hash, add new methods and instance variables
class Book < Hash
   def reindex
     @index = .....
   end
end

# (b) create a new class from scratch, containing a hash, 
#    and define needed methods for the contained hash
class Book
  def initialize(hash)
    @data = hash
  end 
  def []=(k,v)
    @data[k] = v
  end
  # etc....
  def reindex
    @index = ....
  end

# (c) like (b) but using method_missing

# (d) like (b) but using delegation

Ruby には特定のタスクを達成する方法が複数あることは理解していますが、比較的単純なケースで上記のどの方法が望ましいかについての一般的な規則はありますか?

4

1 に答える 1

15

ハッシュのようなオブジェクトに特定のハッシュ メソッドを持たせたくない場合は、オブジェクトを独自のクラスでラップし、必要なメソッドのみを公開します (オプション b)。

いくつかの動作を追加して真のハッシュ動作を維持したい場合は、コア ハッシュ クラスを変更せずに、モジュール内のその動作をハッシュ オブジェクト自体に追加します。

module SpecialHash
  def reindex
    # method def
  end
end

my_hash = {}
my_hash.extend(SpecialHash)
my_hash.reindex #now is defined on my hash

ほとんどの場合、これらのオプションのいずれかでうまくいきます。

一般に、クラスの継承ではなくモジュールを使用してクラスの動作を拡張することを好む傾向があります。これは、よりクリーンで軽量なアプローチであると考えるからです。新しいクラスを作成すると、ドメイン モデルに新しい「もの」を追加しているような気分になります。これは問題なく、まさに無数のシナリオでやりたいことですが、Ruby の mixin 機能は、実際にはそこまでする必要がない場合に非常に優れた代替手段を提供します。

私がクラスの作成に取り組む主な時期は、追跡したい追加の状態がオブジェクトにある場合です。私の追加がオブジェクトの状態を拡張することではなく、その動作を拡張することである場合、ほとんどの場合、モジュールを使用してその動作をそのクラスの既存のインスタンスに混合することから始めます。

この種の質問に対する別の回答も、覚えておく価値のある他のいくつかのポイントをもたらします: ルビーの継承とミックスイン

于 2013-01-06T21:13:06.137 に答える