Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the right way to implement equality in ruby

Tags:

equality

ruby

For a simple struct-like class:

class Tiger   attr_accessor :name, :num_stripes end 

what is the correct way to implement equality correctly, to ensure that ==, ===, eql?, etc work, and so that instances of the class play nicely in sets, hashes, etc.

EDIT

Also, what's a nice way to implement equality when you want to compare based on state that's not exposed outside the class? For example:

class Lady   attr_accessor :name    def initialize(age)     @age = age   end end 

here I'd like my equality method to take @age into account, but the Lady doesn't expose her age to clients. Would I have to use instance_variable_get in this situation?

like image 365
Pete Hodgson Avatar asked Dec 19 '09 01:12

Pete Hodgson


People also ask

How do you use equal in Ruby?

Equality operators: == and != The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not. The != operator, also known as inequality, is the opposite of ==. It will return true if both objects are not equal and false if they are equal.

What does == mean in Ruby?

== Checks if the value of two operands are equal or not, if yes then condition becomes true. (a == b) is not true. !=

How do you check if a string is equality in Ruby?

Two strings or boolean values, are equal if they both have the same length and value. In Ruby, we can use the double equality sign == to check if two strings are equal or not. If they both have the same length and content, a boolean value True is returned. Otherwise, a Boolean value False is returned.


1 Answers

To simplify comparison operators for objects with more than one state variable, create a method that returns all of the object's state as an array. Then just compare the two states:

class Thing    def initialize(a, b, c)     @a = a     @b = b     @c = c   end    def ==(o)     o.class == self.class && o.state == state   end    protected    def state     [@a, @b, @c]   end  end  p Thing.new(1, 2, 3) == Thing.new(1, 2, 3)    # => true p Thing.new(1, 2, 3) == Thing.new(1, 2, 4)    # => false 

Also, if you want instances of your class to be usable as a hash key, then add:

  alias_method :eql?, :==    def hash     state.hash   end 

These need to be public.

like image 134
Wayne Conrad Avatar answered Sep 23 '22 21:09

Wayne Conrad