I should mention that you’d also have to include Comparable to inherit
the rest of the operators.
The method <=> returns -1, 0, or 1; which the other methods can use for
their responses.
You can define the method <=> to allow comparison between objects.
[…]
or maybe something like this?
def <=> other
( bar + baz ) <=> ( other.bar + other.baz )
end
That’s probably not what the OP wants. It would return true for
lorem.bar = 1
lorem.baz = 2
ipsum.bar = 2
ipsum.baz = 1
The <=> operator is useful for objects that have a natural ordering.
This might not make sense here. (What would be the natural, distinct
ordering of songs with a title and an artist? Which attribute
should have higher priority?..)
To test for equality of all attributes, you could simply do
def ==(other)
bar == other.bar && baz == other.baz
end
(This will work fine as long as you only compare objects of the
same class.)
rhs.instance_variable_get(var)
end
return true
end
Note that the first line of this can be changed according to taste:
as above, two objects will compare as equal if the class of the right
hand side is the same as or a sub-class of the left hand side
remove it completely in which case you get “duck typing” equality (no
relationship needed between classes of object)
change it to “return false unless rhs.class == lhs.class” in which
case the two objects must be of the same class
In the first case, a == b will not necessarily return the same as b ==
a.
Also, note that this code allows the right hand side to have extra
instance variables that the left hand side does not, but they can still
compare as equal. That may or may not be desirable. If not, you need to
test for it as well. Again, the way I’ve written it, a == b is not the
same as b == a.
On Mon, Jun 17, 2013 at 4:25 PM, Graham Menhennitt
<[email protected]
wrote:
attr_accessor :bar, :baz
class Foo
def ==(rhs)
hand side is the same as or a sub-class of the left hand side
as b == a.
Perhaps, but I think this is not a good approach.
It’s too magical:
You give up control of what constitutes equality (these kind of
implicit
assumptions seem to always break down)
You store something in a var and all of a sudden your objects aren’t
showing up equal. It really sucks when making some change that doesn’t
matter suddenly causes everything to break for no obvious reason.
You can’t look at the behaviour and figure out what it’s doing, b/c
it’s
violating encapsulation.
It’s suddenly state based instead of value based:
Say you have a method that lazily initializes some var: def users() @users ||= [] end and someone called obj.users.any? on the one, but
not
the other. Now your objects aren’t equal.
It doesn’t matter if bank1 has @pennies=100@dollars=0 and bank2 has
@pennies=0@dollars=1, these have the same value, but it doesn’t matter,
b/c
the state representation is different,
You can’t pass a mock in, b/c it’s no longer about interfaces, it’s
now
about the state of these variables.
That comparison is moot because it is not symmetric (see article linked
below).
remove it completely in which case you get “duck typing” equality (no
violating encapsulation.
All very good points! If this was a relational database we were talking
about the primary key. This is also something we define explicitly and
not
accidentally.