Suppose we want an Animation object that looks like a still
picture, but when you click on it, it goes through an animation
sequence.
Since the ActionListener interface has only one method, it was a
fairly simple matter to define that method and listen for the
botton events in the previous examples. However,
MouseListener has mouseClicked,
mouseEntered,
mouseExited,
mousePressed,
and mouseReleased.
So to implement the Mouselistener interface, we must define all
of the methods, even if we only care about mouseClicked. This
makes us sad :(
However, there is another way. Instead of having to define all
the methods of an interface, we can extend and "adapter" class
which already defines all the methods of the interface with
empty bodies. Then we can simply override the methods we care
about. To support this, the java.awt.event package contains
adapter classes for all eventListener interfaces with multiple
methods. For example, see the mouseAdapter class. This makes us
happy. :)
This approach sounds nice, but there is another problem. If our
Animation class already extends Component, it can't extend the
MouseAdapter beacause a class can only extend one other class -
multiple inheritance isn't allowed. So we are sad again. :(
So what is the solution?
Implement the listener object as a seperate class. :)
We could define the following class in the same file as the
Animation object, since no other class needs it:
class AnimationRequestHandler extends Mouse Adapter{
Animation targetAnimation;
AnimationRequestHandler(Animation a){
targetAnimation = a;
a.addMouseListener(this);
}
public void mouseClicked(MouseEvent e){
targetAnimation.beginAnimation();
}
}
Another approach would be not to save the Animation object in
the AnimationRequestHandler, but instead to use the
MouseEvent.getSource() method to determine the source of the
event. In this case, the Animation object would probably be the
one to call the addMouseListener method, passing an
AnimationRequesthandler as the parameter:
class AnimationRequestHandler extends Mouse Adapter{
public void mouseClicked(MouseEvent e){
if(e.getSource() instanceof Animation){
((Animation)e).getSource().beginAnimation();
}
}
}
:) This is nice because it's short (since we subclass adapter)
and because it isolates the work of handling the events.
The above solution was nice, but we can do better.
One thing to notice about the above solution is that the
Aniimation object and AnimationRequestListener are only loosely
coupled. Even though they are defined in the same file, they
exist as two seperate classes and their objects ahve completely
separate identities. The only way one can know about the other
is to be told about the other object through a parameter to a
constructor or a method.
The above example motivates the need for a way to define classes
that have a closer relationship. We'd like to be able to define
a class that has an instrinsic relationship to another class,
just be virtue of the way its defined.
Java supports several different varieties of such relationships,
through a language feature called inner classes.(see next
set of lecture notes)