Overriding Equality of objects
In ruby the equality of the objects depend upon several things, which are
a) ==
b) hash
c) eql?
In normal cases whenever you run == method for string numbers etc it works perfectly fine, but if there are two identical objects of a class it will always return false.
Lets see an example:
class Car
attr_accessor :name
def initialize(name)
@name = name
end
end
p Car.new("swift") == Car.new("swift")
=> false
Thus we can see it gives the result false, even though both objects are identical. This is so because the hash of the objects are different and if every time you initialize an object it will return different hash value like this:
> Car.new("swift")
=> #<Car:0x000000022d85c8 @name="swift">
> Car.new("swift")
=> #<Car:0x000000022b4808 @name="swift">
Thus you can see the difference here, now suppose if you have a use case like this that if the attributes of the objects are identical then you need to show them as equal. To do that you need to override the == method in your class like this:
class Car
attr_accessor :name
def initialize(name)
@name = name
end
def ==(other_obj)
if self.name == other_obj.name
return true
else
return false
end
end
end
p Car.new("swift") == Car.new("swift")
=> true
p Car.new("swift") == Car.new("fiat")
=> false
Here we have solve the problem of one operator but suppose we have an array of multiple objects and you want to perform uniq on them, then in that case it doesn't only depends upon the == operator. it is also dependent upon the eql? method and hash method. so we also need to override them too.
## before overriding
> [Car.new("swift"), Car.new("swift"), Car.new("swift")]
=> [#<Car:0x000000021c2288 @name="swift">, #<Car:0x000000021c2238
@name="swift">, #<Car:0x000000021c21e8 @name="swift">]
Now we will override eql? method and hash method
class Car
attr_accessor :name
def initialize(name)
@name = name
end
## Overriding == method
def ==(other_obj)
if self.name == other_obj.name
return true
else
return false
end
end
## Overriding eql method
def eql?(other_obj)
if self.name == other_obj.name
return true
else
return false
end
end
## Overriding hash method
## Here we will just use the hash for the name attribute
def hash
self.name.hash
end
end
Now if you run the uniq on identical object array you will get only one element
> [Car.new("swift"), Car.new("swift"), Car.new("swift")].uniq
[#<Car:0x00000002059f18 @name="swift">]
0 Comment(s)