- Design Patterns
- A Pattern Example
- Don't Be Misled by Design Patterns
- An Aside on MouseAdapter
- Conclusion
An Aside on MouseAdapter
I find a common bug when writing software of the following form:
class MyMouseAdapter extends MouseAdapter implements MouseListener { public void mouseClicked() { // do something } }
Despite the comment that this code should do something, it actually does nothing whatsoever when the mouse is clicked. That's because the mouseClicked method is supposed to take a MouseEvent argument. This code is just fine by the Java compiler, since MyMouseAdapter does implement all of MouseListener by way of MouseAdapter. The new method overloads the name mouseClicked, but it doesn't override the existing definition, which does nothing when the mouse is clicked.
Be careful when using the MouseAdapter or any of java.awt.event's other Adapter classes. They'll save you some time if you're interested only in the mouseClicked eventbut not mousePressed, mouseReleased, or the mouse entering and exiting events, which is not an uncommon scenario. But it could prevent you from getting anything at all unless you're careful. This can be particularly tricky to debug. You can use debuggers and stack traces to figure out why a method is called, but it's much harder to figure out why a method isn't called. Worse, the answer in this case would lie somewhere in the source code to the Java development kit, which is available but not generally part of your debugging cycle. Poking around in there to figure out why a method wasn't called opens you up to several hundred thousand lines of code, and pinpointing the problem can be like finding a needle in a haystack.
On the flip side, and even more subtly, using MouseAdapter "future-proofs" your code. If Sun adds a new event to MouseListener, say mouseDoubleClicked, your code would continue working, since they'd likely modify MouseAdapter at the same time to give a null implementation of that event. Your code would break if it just implemented MouseListener, since it wouldn't have the mouseDoubleClicked event.
Fortunately, Sun doesn't usually change classes in this way. More likely, they'd create MouseListener2 with the added method. That's what they did when they wanted to extend the capabilities of LayoutManager; they added the new methods to LayoutManager2. Old LayoutManagers continued to work, while new layout managers could implement the new methods. It took some extra work on their part to be able to deal with either the old or the new versions of this class, but they felt (correctly) that it was better for them to do the work than for millions of programmers to have to change untold numbers of existing classes.
To sum up this little aside, notification interfaces tend to be relatively long-lived, since they're contracts between classes. Empty implementations of these interfaces can save time if you only care about some of the events that may occur, but they have the potential to confuse you during debugging when code paths you expected to be called don't happen.