Что правильный путь состоит в том, чтобы реализовать равенство в рубине

Для простого подобного структуре класса:

class Tiger
  attr_accessor :name, :num_stripes
end

что корректный путь состоит в том, чтобы реализовать равенство правильно, для обеспечения этого ==, ===, eql?, и т.д. работа, и так, чтобы экземпляры класса играли приятно в наборах, хешах, и т.д.

Править

Кроме того, что хороший путь состоит в том, чтобы реализовать равенство, когда Вы хотите выдержать сравнение на основе состояния, это не представило вне класса? Например:

class Lady
  attr_accessor :name

  def initialize(age)
    @age = age
  end
end

здесь я хотел бы, чтобы мой метод равенства принял @age во внимание, но Леди не представляет свой возраст клиентам. Я должен был бы использовать instance_variable_get в этой ситуации?

50
задан Pete Hodgson 20 December 2009 в 08:56
поделиться

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

Они должны быть публичными.

69
ответ дан 7 November 2019 в 10:55
поделиться

Обычно с помощью оператора == .

def == (other)
  if other.class == self.class
    @name == other.name && @num_stripes == other.num_stripes
  else
    false
  end
end
1
ответ дан 7 November 2019 в 10:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: