We can now see why Java is at fault. Consider first the complex-number
example. The asymmetry of addition --- u.add(v)
--- arises
because no method can be attached to more than one class. This rule is
enforced by Java's syntax, whereby every method's definition must occur
textually inside its class. In this, Java differs from some other
object-oriented languages such as the Common Lisp Object System
[Steele].
This syntactic property reflects something more fundamental. Conventional
OOP - Java included - abstracts from the notion of an object by
replacing physical space by the computer's address space. The identity
of an object is given by its location in store. Object-valued variables
contain pointers to these locations: if variables a
and b
point at the same location, they identify the same object. And if
a
points at the same location now as it did ten statements ago,
then it identifies the same object, even if all of that object's
attributes have been changed by altering its instance variables. This is
explained in Chapter 2 of [Flanagan], and is familiar ground to anyone
who has programmed with pointers.
Just as address space gives OOP objects their identity, methods give them their behaviour. The idea behind a method is that it is a means of acting upon an object: changing it while allowing it to retain its identity. We see this very often in graphical user interfaces: a window object will typically be equipped with a method for resizing itself, a method for moving itself across the screen, a method for writing characters into it, and so on. It is natural to attach each method to the object on which it acts.
However, if complex numbers are not objects, then they should not have
methods. Following mathematical practice,
we should use functions for operating on indiscernables. Functions are
not assymetric: in a+b
, the /+/ does not ``belong'' either to
a
or to b
.
Implementing indiscernables as objects also explains the behaviour of equality
in our second symptom. Two strings may have the same character contents;
two complex numbers may contain the same real and imaginary parts; but if
they reside in different locations, Java treats them as different objects, and
==
reflects this by returning false.