Почему проверка равенства для экземпляра Struct / Class отличается? - PullRequest
0 голосов
/ 01 января 2019

Я не понимаю разницы между проверкой равенства структур и классов.Поскольку и Struct, и Class получают свои #hash от ядра, но, похоже, они ведут себя по-разному.

Я знаю, что instance.hash выдаст разные результаты для каждого экземпляра класса.Экземпляр Struct имеет разных предков [Customer, Struct, Enumerable, Object, Kernel, BasicObject] по сравнению с экземпляром класса [Foo, Object, Kernel, BasicObject].Что в действительности заставило каждый экземпляр Class иметь свой хеш-номер, чтобы

Customer = Struct.new(:name, :phone, :address) do

end

class Foo
  def initialize(the_name, phone, address)
    @name = the_name
    @phone = phone
    @address = address
  end
end


str_a = Customer.new('bond', 'ring', 'address')
str_b = Customer.new('bond', 'ring', 'address')

foo_a = Foo.new('bond', 'ring', 'address')
foo_b = Foo.new('bond', 'ring', 'address')

p str_a == str_b #true
p foo_a == foo_b #false

p str_a.hash # 4473040617195177332
p str_b.hash # 4473040617195177332
p foo_a.hash # -3118151143418428190
p foo_b.hash # -1042397847400824657

p str_a.method(:hash).owner #Kernel
p foo_a.method(:hash).owner #Kernel

, и Struct, и Class используют Kernel для генерации hash_number.Почему другой экземпляр Class создает другой хэш int, а экземпляр Struct создает тот же самый int хэш?

1 Ответ

0 голосов
/ 01 января 2019

Я думаю, что ответ, который вы ищете, найден в документации Struct

Equality—Returns true if other has the same struct subclass 
and has equal member values (according to Object#==).

В вашем примере одинаковые значения элементов для str_a и str_b, и ониимеют один и тот же подкласс (Customer), поэтому они равны по сравнению с ==

Сравните это с Документация по объекту

Equality — At the Object level, == returns true only if 
obj and other are the same object. Typically, this method is
overridden in descendant classes to provide class-specific meaning.

В вашем примере, foo_a и foo_b - это не один и тот же объект (потому что это не один и тот же экземпляр)

Если вы ищете почему они разные, я не оченьответь на этот вопросТолько то, что поведение, как задумано в документах.На самом деле они не имеют одинаковый идентификатор:

pry >> Bar = Struct.new(:name) do; end
=> Bar < Struct
pry >> x = Bar.new
=> #<Struct:Bar:0x7f8ebca47610
        name = nil

pry >> y = Bar.new
=> #<Struct:Bar:0x7f8ebca14058
        name = nil

pry >> x.name = "foo"
=> "foo"
pry >> y.name = "foo"
=> "foo"
pry >> x
=> #<Struct:Bar:0x7f8ebca47610
        name = "foo"

pry >> y
=> #<Struct:Bar:0x7f8ebca14058
        name = "foo"

Но вы заметите, что сравнение основано на атрибутах, а не на идентификаторе объекта:

pry >> x == y
=> true

Даже если объектИдентификаторы разные:

pry >> x.__id__
=> 70125513489160
pry >> y.__id__
=> 70125513383980
...