Previous | Table of Contents | Next |
14.3.6.7. Finalizer Chaining?
You might assume that since Java chains constructor methods that it also automatically chains the finalizer methods for an object. In other words, you may think that the finalizer method of a class automatically invokes the finalizer of its superclass. In fact, Java does not do this. In practice, finalizer methods are relatively rare, and the need for finalizer chaining rarely arises. If a class B with a finalizer method is a subclass of a class A with its own finalizer method, then Bs finalizer should be sure to invoke As finalizer, explicitly creating a chain of finalizers. This is a little tricky, since finalizers always have the same name (finalize()), and we havent yet learned how to invoke a method in the superclass when that method is also defined in the subclass. Well return to the issue of finalizer chaining when we learn how.
14.3.6.8. Shadowed Variables
Suppose that our GraphicCircle class has a new variable that specifies the resolution, in dots per inch, of the DrawWindow object in which it is going to be drawn. And further, suppose that it names that new variable r:
public class GraphicCircle extends Circle { Color outline, fill; float r; // New variable. Resolution in dots-per-inch. public GraphicCircle(double x, double y, double rad, Color o, Color f) { super(x, y, rad); outline = o; fill = f; } public void setResolution(float resolution) { r = resolution; } public void draw(DrawWindow dw) { dw.drawCircle(x, y, r, outline, fill); } }
Now, with this resolution variable declared, when we use the variable r in the GraphicCircle class, we are no longer referring to the radius of the circle. The resolution variable r in GraphicCircle shadows the radius variable r in Circle.20
20This is a contrived example, of coursewe could simply rename the variable and avoid the issue. Typically, we would rename the variable: Variable shadowing is a necessary part of Java syntax, but is not a useful programming technique. Your code will be easier to understand if you avoid shadowed variables.
So, how can we refer to the radius variable defined in the Circle class when we need it? Recall that using a variable, such as r, in the class in which it is defined is shorthand for:
this.r // Refers to the GraphicCircle resolution variable.
As you might guess, you can refer to a variable r defined in the superclass like this:
super.r // Refers to the Circle radius variable.
Another way you can do this is to cast this to the appropriate class and then access the variable:
((Circle) this).r
This cast is exactly what the super keyword does when used like this. You can use this casting technique when you need to refer to a shadowed variable defined in a class that is not the immediate superclass. For example, if C is a subclass of B, which is a subclass of A, and class C shadows a variable x that is also defined in classes A and B, then you can refer to these different variables from class C as follows:
x // Variable x in class C this.x // Variable x in class C super.x // Variable x in class B ((B)this).x // Variable x in class B ((A)this).x // Variable x in class A super.super.x // Illegal; does not refer to x in class A.
Note that you cannot refer to a shadowed variable x in the superclass of a superclass with super.super.x. Java does not recognize this syntax.
14.3.6.9. Shadowed Methods?
Just as a variable defined in one class can shadow a variable with the same name in a superclass, you might expect that a method in one class could shadow a method with the same name (and same arguments) in a superclass. In a sense, they do: Shadowed methods are called overridden methods. But method overriding is significantly different than variable shadowing; it is discussed in the sections that follow.
When a class defines a method using the same name, return type, and arguments as a method in its superclass, the method in the class overrides the method in the superclass. When the method is invoked for an object of the class, it is the new definition of the method that is called, not the superclasss old definition.
Method overriding is an important and useful technique in object-oriented programming. Suppose we define a subclass Ellipse of our Circle class.21 Then it would be important for Ellipse to override the area() and circumference() methods of Circle. Ellipse would have to implement new versions of these functions because the formulas that apply to circles dont work for ellipses.
21This is admittedly a strange thing to do, since, mathematically, a circle is a kind of ellipse, and it is customary to derive a more specific class from a more general one. Nevertheless, it is a useful example here.
Before we go any further with the discussion of method overriding, be sure that you understand the difference between method overriding and method overloading, which we discussed earlier. As you probably recall, method overloading refers to the practice of defining multiple methods (in the same class) with the same name but with differing argument lists. This is very different from method overriding, and it is important not to get them confused!
Previous | Table of Contents | Next |