Уникальность Ruby Instances - PullRequest
       6

Уникальность Ruby Instances

1 голос
/ 15 июля 2010

Если я создаю два экземпляра String с одинаковым содержимым по отдельности, они идентичны.Это не относится к пользовательским классам по умолчанию (см. Пример ниже).

Если у меня есть свой собственный класс (Test ниже), и у меня есть переменная (@v ниже), которая является уникальной, т.е.,два Test экземпляра с одинаковым @v должны рассматриваться как идентичные, тогда как мне сказать Руби, что это так?

Рассмотрим этот пример:

class Test
  def initialize(v)
    @v = v
  end
end

a = {Test.new('a') => 1, Test.new('b') => 2}

a.delete(Test.new('a'))

p a
# # Desired output:
# => {#<Test:0x100124ef8 @v="b">=>2}

Ответы [ 4 ]

1 голос
/ 15 июля 2010

В большинстве случаев объект, который необходимо сопоставить и / или хэшировать, состоит из переменных-членов, которые являются либо примитивами (целыми числами, строками и т. Д.), Либо сами по себе сопоставимы / хешируемы.В этих случаях этот модуль:

module Hashable

  include Comparable

  def ==(other)
    other.is_a?(self.class) && other.send(:parts) == parts
  end
  alias_method :eql?, :==

  def hash
    parts.hash
  end

end

может быть просто включен в ваш класс, чтобы позаботиться обо всей занятой работе.Все, что вам нужно сделать, это определить метод "parts", который возвращает все значения, составляющие состояние объекта:

class Foo

  include Hashable

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

  private

  def parts
    [@a, @b]
  end

end

Объекты, построенные таким образом, сравнимы (они имеют <, <=, ==,> =,>,! = и equ?) и они могут быть хеш-ключами.

1 голос
/ 15 июля 2010

Вы используете объекты класса Test в качестве ключей для хеша. Для того, чтобы это функционировало должным образом (и, следовательно, a.delete), вам нужно определить два метода внутри Test: Test#hash и Test#eql?

От: http://ruby -doc.org / core / classes / Hash.html

Хэш использует key.eql? проверить ключи для равенство. Если вам нужно использовать экземпляры ваших собственных классов в качестве ключей в хэше, рекомендуется определить оба EQL? и методы хеширования. Хеш Метод должен иметь свойство, которое a.eql? (b) подразумевает a.hash == b.hash.

1 голос
/ 15 июля 2010

Я нашел другой способ справиться с этим, отслеживая все экземпляры Test внутри, я могу вернуть предварительно созданный экземпляр, а не создавать новый и сказать ruby, что они эквивалентны:* Сейчас Test.new('a') == Test.new('a') и Test.new('a') === Test.new('a'):)

1 голос
/ 15 июля 2010

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

class Test
  def initialize(v)
    @v = v
  end
  def ==(other)
    @v == other.instance_variable_get(:@v)
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...