}
The intent is that the class HighSpeedPrinter.SerialPort overrides the class
Printer.SerialPort so that serial is set to refer to the correct type of object. But the class
Printer is not affected by the new subclass of SerialPort defined inside HighSpeedPrinter, even
though the new subclass seems to have the same name.
One solution to this design problem is to abstract construction of the inner class objects into a factory method
which can then be overridden in a subclass to construct the right kind of inner class. For example:
class Printer extends Device {
class SerialPort extends Port {
// ...
}
Port serial = createSerialPort();
protected Port createSerialPort() {
return new SerialPort();
}
}
The HighSpeedPrinter class now defines its specialized inner class and overrides the factory method to
construct an instance of that class. Now that we realize that nested type definitions hide and don't override, we
aren't tempted to use the same name for the inner class, for we know that hiding is usually a bad thing.
class HighSpeedPrinter extends Printer {
class EnhancedSerialPort extends SerialPort {
// ...
}
protected Port createSerialPort() {
return new EnhancedSerialPort();
}
}
Now when a HighSpeedPrinter is constructed and the initializers in Printer execute, we invoke the
overriding createSerialPort method that returns an instance of EnhancedSerialPort.
This is one example of a situation in which a method of the subclass is invoked before the subclass object has
been fully constructed and so care must be taken to ensure that things work correctly. For example, if
EnhancedSerialPort initializes a field using a field from the enclosing HighSpeedPrinter
instance, then at the time the EnhancedSerialPort object is constructed, the fields of the enclosing
object will have the default "zero" values for their type.
An alternative design would have the constructor for HighSpeedPrinter simply reassign serial to
refer to an EnhancedSerialPort object. However, that approach causes the unnecessary construction of
the original SerialPort object, and that construction may be non-trivial and undesirablein this example it
may involve configuring hardware.
5.6. Nesting in Interfaces
You declare nested classes and interfaces in an interface for the same reason that you declare nested classes