Overriding Equality

Identity is such a fundamental Smalltalk notion that if you override the `==` method Smalltalk ignores your override. By contrast, you can override the `=` method at will. ⇒ The Equal Sign

Therefore, in your own classes, the definition of equality – “indistinguishability” – is entirely up to you. As a case in point, Smalltalk's designers decided on their own defi­nition of equality for strings, namely that two strings are equal if they contain the same characters in the same order. But before you override equality in your classes, read the upcoming section "Overriding equality."

We've seen that developers have the prerogative of overriding the `=` method as they please in their own classes (page 74). Those who do, however, risk introducing a subtle bug into their programs. They will find, for instance, that objects they add to a set may appear not to be there later on. I call this the “anomaly of the disappearing element," and you will experiment with it in the exercise in the next section.

Here’s how the anomaly occurs; sets use hashing to determine where to insert an added object, and the default hashing algorithm produces different hash values for two distinct (non-identical) objects. The set therefore tends to place non-identical objects in different positions, which is ordinarily desirable and harmless. But if the developer overrides the `=` method so that the two distinct objects are equal, adds the first one to the set, then searches the set to see if the second, equal one is present, *expecting that it is*, he will find that it isn't. That's because the set will begin its search at a different position, determined by the different hash value of the second object. The developer's error was to expect the second object to behave as though it were identical to the first, when in fact it is only equal to the first.

This scenario may seem unlikely, but it arises in client/server systems, which commonly use a proxy for an object to stand in for the object itself. To determine which proxy stands for which object, the system uses an overridden equality test that compares a problem-specific datum (like a social security number or other unique identifier) in the proxy and the object. Although the proxy and its object aren't identical, they are equal because they have the same identifying datum. The system then treats the proxy and its object as though they are the same, which was the purpose for overriding equality. But it also exposes the system to the “anomaly of the disappearing element." The different hash results of the proxy and the proxied object specify different positions for the two objects:

To prevent this anomaly, whenever you override the `=` method for a class, also override the `hash` method. Whatever the `=` method compares, write the `hash` method so that it hashes the same thing. In the client/server example above, if the `=` method compares a social security number, write the `hash` method so that it too hashes the social security number. This ensures that when a set hashes to determine the position of an object, it will compute the same position for both the proxy and its object.

[…]

~

Chamond Liu, Smalltalk, Objects, and Design: The Classic Guide, Now in Paperback, Reprinted from the original 1996 ed. with minor corrections (San Jose: toExcel, 2000), p. 74.

⇒ same nameDistinction

DOT FROM lambda-browsing