web-dev-qa-db-ja.com

ruby)で平等を実装する正しい方法は何ですか

単純な構造体のようなクラスの場合:

class Tiger
  attr_accessor :name, :num_stripes
end

=====eql?などが機能し、クラスのインスタンスがセットやハッシュなどでうまく機能するようにするために、同等性を正しく実装する正しい方法は何ですか。

[〜#〜]編集[〜#〜]

また、クラスの外部に公開されていない状態に基づいて比較したい場合に、平等を実装するための優れた方法は何ですか?例えば:

class Lady
  attr_accessor :name

  def initialize(age)
    @age = age
  end
end

ここでは、平等方法で@ageを考慮に入れたいのですが、Ladyは彼女の年齢をクライアントに公開していません。この状況でinstance_variable_getを使用する必要がありますか?

47
Pete Hodgson

複数の状態変数を持つオブジェクトの比較演算子を簡略化するには、オブジェクトのすべての状態を配列として返すメソッドを作成します。次に、2つの状態を比較します。

class Thing

  def initialize(a, b, c)
    @a = a
    @b = b
    @c = c
  end

  def ==(o)
    o.class == self.class && o.state == state
  end

  protected

  def state
    [@a, @b, @c]
  end

end

p Thing.new(1, 2, 3) == Thing.new(1, 2, 3)    # => true
p Thing.new(1, 2, 3) == Thing.new(1, 2, 4)    # => false

また、クラスのインスタンスをハッシュキーとして使用できるようにする場合は、次を追加します。

  alias_method :eql?, :==

  def hash
    state.hash
  end

これらは公開する必要があります。

68
Wayne Conrad

すべてのインスタンス変数の同等性を一度にテストするには:

def ==(other)
  other.class == self.class && other.state == self.state
end

def state
  self.instance_variables.map { |variable| self.instance_variable_get variable }
end
19
jvenezia

通常は==演算子。

def == (other)
  if other.class == self.class
    @name == other.name && @num_stripes == other.num_stripes
  else
    false
  end
end
1
Robert K