The gates seem to be open for serious revisions to the Java language in Java 7. Thus it’s worth reviewing why some things are just flat out bad ideas for any language, because too many developers either never knew this or have forgotten it. First up: operator overloading:
It’s not a coincidence that almost every C++ text written in the last ten years recommends extreme caution when overloading operators. For example, here’s Bruce Eckel in Chapter 10 of Thinking in C++:
It’s very tempting to become overenthusiastic with operator overloading. It’s a fun toy, at first. But remember it’s only syntactic sugar, another way of calling a function. Looking at it this way, you have no reason to overload an operator except that it will make the code involving your class easier to write and especially read. (Remember, code is read much more than it is written.) If this isn’t the case, don’t bother.
If anything, Eckel is too kind to operator overloading. What’s really wrong with operator overloading? Let me count the problems:
The most serious problem is that operator overloading leads to illegible code. You can no longer tell what any given chunk of code is doing. Sometimes it’s obvious, as when someone is adding two complex numbers. Most of the time it’s not. For instance suppose someone is dividing two matrices. What does that mean when one matrix isn’t invertible? Worse yet, suppose someone adds two database records? or subtracts two addresses? Outside a very limited mathematical realm, operators don’t have any well understood meanings. It’s much better to have a full method name such as
Few use cases
There are some good uses cases for operator overloading. Complex arithmetic is one.
BigDecimal are two more. These are all instances of mathematical rings or at least groups, where the operations of addition, multiplication, division, and subtraction are well-defined. (Groups may only define addition and subtraction.)
However, there just aren’t that many groups, rings, and fields out there which are likely to come up in most programmers’ every day practice. By my count they’re only maybe ten or so more that really make sense.
If something isn’t a group or ring, then the various symbols just don’t fit it. A full-blown method name will be more descriptive, more accurate, and less likely to confuse readers.
Do you remember all the precedence rules of high school algebra? Do you remember all the precedence rules of your language of choice? (Personally, I answer yes to the first and no to the second.) You need to know both sets of rules inside and out to have any hope of getting operator overloading correct. You can’t just bang out a
+ method and expect it to work.
That’s not all either. To properly overload an operator you need to understand transitivity, commutativity, and distributivity; when they do and don’t apply; how they relate to the various operators; and how they match method invocations.
Maybe you’re a math hot shot and can keep all this straight, but do you trust the guy down the hall from you to be equally competent? Remember, it’s his code you’re going to have to debug.
Keep in mind, many programmers can’t even reliably write an
equals() method that satisfies basic commutativity requirement that
b.equals(a) . Do you really want to trust these same doofuses to follow the much more stringent requirements for
Many people object that Java already has operator overloading. For instance, you can use the plus sign both to add ints and to concatenate strings. Anyone making this argument does not understand what’s at issue, and their opinions can be discounted.
Using the same symbol for two different built-in operations is completely different from operator overloading. For instance, almost every language supports this including languages like Basic and C. Adding two ints is not the same operation as adding two doubles, or as adding an int to a double. However, all three different operations use the plus sign in most languages.
This is not a problem because the plus sign is still unambiguous. It means the same thing in everyone’s code. There’s no confusion. This is completely different from allowing my code to mean one thing when it adds two database records and your code to mean something completely different.
Operator overloading just doesn’t make sense. While there are legitimate use cases for it, there aren’t enough of them. While it makes some code cleaner, it makes much more code dirtier. While it can be used competently by the most cautious programmers, it is far more likely to be used incorrectly by the rest of us. In C++ operator overloading is a major contributor to illegible, unmaintainable code where bugs hide. Operator overloading: just say no.