Vitalii Paprotskyi
Vitalii Paprotskyi

Reputation: 389

eql? override doesn't work in Hash

Hash checks its keys with eql?:

foo = 'str'
bar = 'str'

foo.equal?(bar)   #=> false
foo.eql?(bar)     #=> true

h = { foo => 1 }
h[foo]            #=> 1
h[bar]            #=> 1

But this doesn't work if I use my own class as a key:

class Cl
    attr_reader :a
    def initialize(a)
        @a = a
    end
    def eql?(obj)
        @a == obj.a
    end
end

foo = Cl.new(10)
bar = Cl.new(10)

foo.equal?(bar)   #=> false
foo.eql?(bar)     #=> true

h = { foo => 1 }
h[foo]            #=> 1
h[bar]            #=> nil

Why does the last line return nil instead of 1?

Upvotes: 0

Views: 84

Answers (1)

Leventix
Leventix

Reputation: 3869

eql? must be used in conjunction with a hash method that returns a hash code:

class Cl
  attr_reader :a
  def initialize(a)
    @a = a
  end
  def eql?(obj)
    @a == obj.a
  end
  def hash
    @a
  end
end

See this blog post.

Upvotes: 1

Related Questions