Page 584 - Introduction to Programming with Java: A Problem Solving Approach
P. 584
550 Chapter 13 Inheritance and Polymorphism
how to perform this rotation around the window’s midpoint. But the rotation doesn’t actually occur until after the object is painted.
The next step is instantiating a GeneralPath object and assigning it to the reference variable called shape. Initially this shape is nothing more than our previously defined rectangle. Then shape’s append method adds the backEllipse component, so that shape now includes everything in either the rectangle or the back-side ellipse.
Before it actually paints, the program must specify the coloring scheme with a setPaint method call. The setPaint parameter must be a reference to an object that implements the Paint interface. If you look up the API documentation for the GradientPaint class, you’ll see that, yes, it implements the Paint interface. Since our gradientPaint object is an instance of the GradientPaint class, and since the GradientPaint class implements the Paint interface, the program can call setPaint with a reference to the gradientPaint object as the argument. At this point, the program is ready to paint the sides of the cylinder with the fill(shape) method call. This tells the computer to perform the previously specified method of painting in the previously specified shape, and then rotate the result as previously specified.
The last three statements in the program paint the visible end of the cylinder. The first statement cal- culates intensity based on the angle of the visible end—using a lighter shade when we’re looking directly at the end and a darker shade when we see it at a grazing angle. The setColor method call changes the paint mode from the previously established gradient painting to a flat gray having the just-computed intensity. The final fill(frontEllipse) method call tells the computer to paint the front ellipse shape and then rotate the result as previously specified.
Figure 13.24c contains several examples where API input parameter types are interfaces rather than classes. The GeneralPath constructor’s parameter is of type Shape, where Shape is an interface. The object called rectangle confAormpsatogthois bePcauDseFits cElasns, hReactnancgler, implements the Shape interface. The first parameter in GeneralPath’s append method and the parameter in Grahpics2D’s fill method are also of type Shape. The objects called backEllipse, shape and frontEllipse all conform because their classes, Ellipse2D and GeneralPath, both implement the Shape interface, too. Graphics2D’s setPaint method receives a parameter of type Paint, where Paint is another in- terface. The object called gradientPaint conforms to this because its class, GradientPaint, imple- ments the Paint interface. These are all polymorphic references!
Summary
• The Object class is the ancestor of all other classes.
• To avoid using the Object class’s equals method, for each of your classes, you should define an
equals method that compares instance variable values.
• To avoid the Object class’s mysterious response to a toString method call, for each of your classes,
you should define a toString method that outputs a string concatenation of instance variable values.
• At compile time, the compiler confirms that a reference variable’s class is able to handle each of the reference variable’s method calls in some way. At runtime, the JVM looks at the particular type of the object referred to by the reference variable to determine which one of several alternative polymorphic
methods should actually be called, and it binds the object to that method.
• The instanceof operator enables you to determine explicitly whether the object referred to by a
reference variable is an instance of a particular class or descended from that class.
• You can always assign an object to a more generic reference variable, because the object’s methods in-
clude methods inherited from the reference variable’s class.