Search code examples
javaabstract-class

Why an abstract class is "considered incomplete"?


We known that an abstract class is an incomplete class (all its methods are unimplemented - # abstract method), but abstract class is also known that "a class is CONSIDERED INCOMPLETE". So, what is the correct meaning (definition) of CONSIDERED INCOMPLETE, is that a class can have both implemented and unimplemented method? or another context?

Please let me know, thank you very much!


Solution

  • The specification says "An abstract class is a class that is incomplete, or to be considered incomplete" because you can have an abstract class that is fully implemented (see java.awt.event.MouseAdapter as an example). Technically, it is complete, but it is not meant to be used this way.

    Nowadays, one might implement those abstract adapter classes by interfaces with default methods (if for that particular case an interface would be appropriate for that purpose at all …).


    The idea behind the adapter classes was to provide a base implementation of particular interface that allows only those methods that are of interest for the current use case.

    The interfaces java.awt.event.MouseMotionListener and java.awt.event.MouseWheelListener that are implemented by java.awt.event.MouseAdapter are not very well suited to illustrate the benefit of this approach, because they do have only two or one method. In addition, that MouseAdapter class implements also java.awt.event.MouseListener but does not implement any method from that interface …

    So lets have a closer look to the class java.awt.event.KeyAdapter that implements the interface java.awt.event.KeyListener. According to the description for java.awt.event.KeyEvent, an implementation of KeyListener will receive three events for each character you type (for the exact details, refer to the description of KeyEvent):

    1. KEY_PRESSED – handled by keyPressed()
    2. KEY_TYPED – handled by keyTyped(), but only if a valid Unicode character could be generated
    3. KEY_RELEASED – handled by keyReleased()

    If your program wants to respond to text input only, it is only interested on the KEY_TYPED events and the implementations of KeyListener.keyPressed() and KeyListener.keyReleased() could remain empty (although they have to be implemented nevertheless!).

    In case you program is an implementation of a game of some kind, you might be more interested in the pressed keys; in that case, KeyListener.typed() may remain empty.

    Next, these listener interfaces are often used as anonymous classes, like this:

    …
    KeyListener listener = new KeyAdapter()
    {
        @Overwrite
        void keyTyped( KeyEvent event )
        {
            // Do something with the event …
        }
    }
    …
    

    Without using the adapter class, the same code would look like this:

    …
    KeyListener listener = new KeyListener()
    {
        @Overwrite
        void keyReleased( KeyEvent event ) { /* Does nothing */ }
    
        @Overwrite
        void keyPressed( KeyEvent event ) { /* Does nothing */ }
    
        @Overwrite
        void keyTyped( KeyEvent event )
        {
            // Do something with the event …
        }
    }
    …
    

    The additional lines do not contribute to readability, not really.

    As said, if the methods in the interface would provide an empty default implementation, the second version (new Interface(){…}) would look like the first one.


    These adapter classes are only one possible use case for an abstract class that does not contain any abstract method. But I confess that most of them would work better with default methods in interfaces – since these default methods made their way into Java, of course! The adapter classes are there since Java 1.1, I think … like those phrase from the language specification!