Переопределить == оператор в Ruby

Согласно документам, Array.include? использует сравнение == для объектов. Я пришел из Java, где такие вещи (обычно) делаются с помощью .equals(), который легко переопределить для конкретного объекта.

Как я могу переопределить == в Ruby, чтобы я мог указать поведение Array.include? для моего конкретного объекта?

Большое спасибо.

3 ответа

Решение

В рубине == это просто метод (с некоторым синтаксическим сахаром на вершине, что позволяет писать foo == bar вместо foo.==(bar)) и вы переопределите == как и любой другой метод:

class MyClass
  def ==(other_object)
    # return true if self is equal to other_object, false otherwise
  end
end

Это не сильно отличается от переопределения равенства в java и, к сожалению, нигде не соблюдается так строго, как должно быть в экосистеме Ruby. Нередко можно найти библиотеки, которые нарушают равенство и ведут себя непредсказуемо, например, при использовании в коллекциях.

  1. При переопределении также переопределяйтеhash; на практике это проще реализовать в Ruby, потому что вы можете делегировать Array или Set для вычисления хеша:[field1, field2].hash
  2. Пожалуйста убедитесь eql?также правильно переопределяется, чтобы гарантировать правильное поведение экземпляров при использовании в качестве ключей в Hash.
  3. Переопределенное равенство должно быть рефлексивным, т.е. a == a должно быть истинным; вы должны использоватьequal?чтобы проверить, является ли это одним и тем же объектом, а затем сократить проверку на равенство, если это так, для существенного повышения производительности.
  4. Замещенное равенство должно быть симметричным, т. е. если a == b, то b == a также должно быть истинным.
  5. Замещенное равенство должно быть транзитивным, т. е. если a == b и b == c, то a == c также должно быть истинным.
  6. Переопределенное равенство должно гарантировать либоtrueилиfalseкак возвращаемое значение. Он никогда не может вызвать исключение.
  7. Простая вещь, за которой нужно следить, это количество спецификаций, которые вы пишете каждый раз, когда переопределяете; вам нужно будет добавить по крайней мере от 5 до 7 спецификаций помимо тех, которые вы могли бы добавить, чтобы покрыть граничные условия для логики равенства.
  8. Как я сказал в начале, остерегайтесь переопределения==при работе с библиотеками и фреймворками. Распространенным случаем является равенство экземпляров ActiveRecord, когда вы можете сломать Rails, если не будете вдумчивы.

Как описано выше, == - это метод Ruby, который можно переопределить. Вы просто запишете условие равенства.

class Person
  attr_reader :name, :gender, :social_id
  attr_accessor :age

  def initialize(name, age, gender, social_id)
    self.name = name
    self.age = age.to_i
    self.gender = gender
    self.social_id = social_id

  def ==(other)
    social_id == other.social_id

Вам больше не нужно переопределять другие методы

Другие вопросы по тегам