Class instances equality

The Problem:

We have the following Color class:

class Color
  def initialize name
    @name = name
  end
end

and we want a Set of uniq Color instances, by their name.

The Issue:

colors = Set.new([Color.new(:red), Color.new(:red)])
=> #<Set: {#<Color:0x007fa9a4239e70 @name=:red>, #<Color:0x007fa9a4239e20 @name=:red>}>

Ouch!
As you can see the Set contains 2 red colors, which is not what we want.

Solution:

From Set class documentation:

Equality of elements is determined according to Object#eql? and Object#hash

So we need to implement these 2 tiny methods in order to make things work:

class Color
  attr_reader :name

  def initialize name
    @name = name
  end

  def eql?(other)
    name == other.name
  end
  alias_method :==, :eql?

  def hash
    name.hash
  end
end

Result:

colors = Set.new([Color.new(:red), Color.new(:red)])
=> #<Set: {#<Color:0x007fa9a389be90 @name=:red>}>

Yey!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s