Yes, the alternative semantics you’re talking about are also entirely possible – this basically means making == behave exactly like eql? (i.e. return true if and only if the objects represent the same value) rather than trying to be “clever”. The following (only showing the definition of the == methods) is what you’re after, I believe:

class Point def ==(other) self.class == other.class && @x == other.x && @y == other.y end end class ColouredPoint < Point def ==(other) super && @c == other.c end end

With the same definitions as above, this gives:

p == q => true p == r => false s == t => false s == u => true p == s => false s == p => false r == s => false s == r => false]]>

“to not allow equals to return false if the classes donâ€™t match”

should have been

“to not allow equals to return true if the classes donâ€™t match”

I picked a bad day to give up coffee.

]]>“Consider your objects p, s and u. s == p is true, p == t is true, but s == t is false.”

should read

“Consider your objects p, s and t. s == p is true, p == t is true, but s == t is false.”

]]>Consider your objects p, s and u. s == p is true, p == t is true, but s == t is false.

A widely adopted solution in Java is to not allow equals to return false if the classes don’t match. I don’t think that would be the expected behaviour in Ruby… so does this mean the transitivity rule is not assumed to hold in general?

]]>class Point attr_reader :x, :y def initialize(x, y) @x, @y = x, y end def ==(other) @x == other.x && @y == other.y end end class ColouredPoint < Point attr_reader :c def initialize(x, y, c) super(x, y) @c = c end def ==(other) super && (!other.respond_to?(:c) || @c == other.c) end end

This gives:

p = Point.new(1, 2) q = Point.new(1, 2) r = Point.new(3, 4) p == q => true p == r => false s = ColouredPoint.new(1, 2, :red) t = ColouredPoint.new(1, 2, :green) u = ColouredPoint.new(1, 2, :red) s == t => false s == u => true p == s => true s == p => true r == s => false s == r => false

Which is what you’re after, yes?

]]>How does Ruby deal with the subclassing symmetry equality problem? e.g. how does one override == for an object named Point which depends on parameters (x, y)? If a subclass ColouredPoint adds an additional RGB value and edits its equality appropriately… how is a == b implies b == a upheld?

]]>It’s a remarkably clear explanation.

I wonder if you can somehow get the relevant pieces of your article incorporated into the core ruby documentation.

thanks!

]]>