Object equality is context sensitive

Equality is context sensitive. It’s very rarely as cut-and-dried as people think it is.

As a simple example, consider two $5 notes. I think everyone can agree that these notes have the same value – they are both worth $5. But are they equal?

No. They are two physically distinct objects. They will be in different physical condition. They have different serial numbers. Depending on the year of printing, they may have different patterns. In fact, they may even have different values, despite being the same denomination – one may be a rare note, and thus collectible. So the only context they are equal in is ‘face value’.

But what about other things with the same value? Are two $5 notes equal to one $10 note? Or ten $1 coins? Or a debit card with a $10 balance? I doubt many people would consider these to be equal, despite having the same value.

When, as a developer, we implement an equals() method, we are choosing a default context for equality. There’s a good chance we won’t get it right for all circumstances. One of the reasons I suggest not implementing equals() for mutable objects is that you automatically take time out of the equality context.

What should be done, instead, is that we should expose better methods that actually say what we mean. For example – the Collection interface in Java defines equality, and does it badly. The implication is that Collections are equal if they contain the same items – but Sets and Lists aren’t equal to each other. Lists are equal if they contain items that are equal in the same order – but SortedSets and LinkedHashSets can’t be equal to a List even if they have the same items in the same order. But a LinkedList and an ArrayList must be equal – because a list is a list is a list, right? Perhaps the Collection interface needs a containsSame() method to complement the containsAll() – and collections where order is important could implement an interface that provides containsSameInSameOrder()? This would probably be better than an equals() method.

(While we’re on the Collections API: note that collections that provide sort functions can all take custom Comparators – because sorting is context sensitive. Yet no collection accepts a custom equality-checker; if you want to provide a custom context for equality, you need to build your own collection class, or decorate incoming objects)

Create fine-grained immutable objects, and implement equality checks there. Coarse-grained objects – even if they are immutable – probably shouldn’t bother with equality checks, because there will be too many contexts for “equality” to be consistently defined. And mutable objects shouldn’t bother, because you automatically leave out the temporal context.

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 20 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 22 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

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 )

Facebook photo

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

Connecting to %s

%d bloggers like this: