You are on page 1of 11

Hour 12.

Making the Most of Existing Objects

This might be a surprise to you, but your Java objects are ideally suited for childbearing. When you create
a program as an object—a set of attributes and behavior—you have designed something that's ready to
pass these qualities on to offspring. Like most offspring, these child objects will take on a lot of the
attributes and behavior of their parent. They can also do some things differently than their parent does;
some extra attributes and behavior can be added that Pop is incapable of.

This system is called inheritance, and it's something every superclass (parent) gives to its subclasses
(children). Inheritance is one of the most useful aspects of object-oriented programming, and you'll be
learning more about it during this hour.

Another useful aspect of object-oriented programming is the capability to create an object that can be used
with different programs. Reusability speeds up the software development process and makes it easier to
develop error-free, reliable programs. Using Java and special development tools, you'll be able to develop
JavaBeans—completely reusable Java objects that are easily incorporated into programs.

The following topics will be covered:

 Superclasses and subclasses

 An inheritance hierarchy

 Overriding methods

 Creating a subclass

 Developing JavaBeans

The Power of Inheritance

Without knowing it, you have used inheritance every time you used one of the standard Java classes such
as String or Math. Java classes are organized into a pyramid-shaped hierarchy of classes in which all
classes descend from the Object class.

A class of objects inherits from all superclasses that are above it. To get a working idea of how this
operates, you'll look at the JApplet class. This class is a superclass of all Swing applets, Java programs
written to run on the World Wide Web. The JApplet class, which is used to create Java 2 applets, is a
subclass of Applet.

A partial family tree of JApplet is shown in Figure 12.1. Each of the boxes is a class, and the lines

connect a superclass to any subclasses below it.


Figure 12.1 The family tree of the Applet class.

At the top is the Object class. JApplet has five superclasses above it in the hierarchy: Applet,
Panel, Container, Component, and Object. The JApplet class inherits attributes and behavior
from each of these classes because each is directly above it in the hierarchy of superclasses. JApplet
does not inherit anything from the five shaded classes in Figure 12.1, which include Dialog and Frame,

because they are not above it in the hierarchy.

If this seems confusing, think of the hierarchy as a family tree. JApplet will inherit from its parent, the

parent's parent, and on upward. It even might inherit some things from its great-great-grandparent,
Object. The JApplet class won't inherit from its siblings or its cousins, however.

Setting up a complicated hierarchy of classes is a difficult thing, but it makes it easier to create new
programs later. The amount of work you need to do to write a new class of objects is reduced. Creating a
new class boils down to the following task: You only have to define the ways in which it is different from an
existing class. The rest of the work is done for you.

As an example, consider the popular video game Tetris. Since the game was invented by Soviet
mathematician Alexey Pajitnov, it has been adapted for dozens of different operating systems, processors,
and programming languages—including several different Java adaptations. In case you somehow avoided
Tetris during the past decade by lapsing into a coma or falling into a deep meditative trance, the game
works as follows: Blocks of different shapes fall from the top of the screen, and you must organize them
into unbroken horizontal lines before they stack up too high.

The Java source file for several adaptations of Tetris is available for your use. If you wanted to create a
new version of Tetris based on one of these existing classes, you could make your game a subclass of an
existing Tetris game. All you would have to do is create the things that are new or different about your
version, and you'd end up with a new game.

Inheriting Behavior and Attributes

The behavior and attributes of a class are a combination of two things: its own behavior and attributes, and
all the behavior and attributes it inherits from its superclasses.

The following are some of the behavior and attributes of Applet:


 The equals() method determines whether an JApplet object has the same value as another

object.

 The setBackground() method sets the background color displayed on the applet window.

 The add() method adds user interface components such as buttons and text fields to the applet.

 The setLayout()method defines how the applet's graphical user interface will be organized.

The JApplet class can use all of these methods, even though setLayout() is the only one it didn't
inherit from another class. The equals() method is defined in Object, setBackground() comes
from Component, and add() comes from Container.

Overriding Methods

Some of the methods defined in the JApplet class of objects were also defined in one of its
superclasses. As an example, the update() method is set up in both the JApplet class and the
Component class. This method was originally used in Java 1.0 to control whether the applet window is
cleared out before anything is drawn in it. In Java 2, the JApplet class has its own update() method

that never clears the applet window. When a method is defined in a subclass and its superclass, the
subclass method is used. This enables a subclass to change, replace, or completely wipe out some of the
behavior or attributes of its superclasses. In the case of update(), the purpose was to wipe out some

behavior present in a superclass.

Creating a new method in a subclass to change behavior inherited from a superclass is called overriding
the method. You need to override a method any time the inherited behavior will produce an undesired
result.

Establishing Inheritance

You establish a class as the subclass of another class with the extends statement, as in the following:

class AnimatedLogo extends javax.swing.JApplet {


// behavior and attributes go here
}

The extends statement establishes the AnimatedLogo class of objects as a subclass of JApplet,
using the full class name of javax.swing.JApplet. As you will see during Hour 17, "Creating
Interactive Web Programs," all Swing applets must be subclasses of JApplet because they need the

functionality this class provides to run on a World Wide Web page.


One method that AnimatedLogo will have to override is the paint() method, which is used to draw all
things that are shown on the program's display area. The paint() method is implemented by the
Component class and is passed all the way down to AnimatedLogo. However, the paint() method
does not do anything. It exists so that subclasses of Component have a method they can use when

something must be displayed when that subclass is running.

To override a method, you must start the method in the same way it started in the superclass from which it
was inherited. A public method must remain public, the value sent back by the method must be the

same, and the number and type of arguments to the method must not change.

The paint() method of the Component class begins as follows:

public void paint(Graphics g) {

When AnimatedLogo overrides this method, it must begin with a statement like this:

public void paint(Graphics screen) {

The only difference is in the name of the Graphics object, which does not matter when determining if the

methods are created in the same way. These two statements match because the following things match:

 Both paint() methods are public.

 Both methods return no value, as declared by the use of the void statement.

 Both have a Graphics object as their only argument.

Using this and super in a Subclass

Two keywords that are extremely useful in a subclass are this and super.

As you learned during the previous hour, the this keyword is used to refer to the current object. When
you're creating a class and you need to refer to the specific object created from that class, this can be

used, as in the following statement:

this.title = "Cagney";

This statement sets the object's title variable to the text Cagney.

The super keyword serves a similar purpose: It refers to the immediate superclass of the object. super

can be used in several different ways:

 To refer to a constructor method of the superclass, as in super("Adam", 12).

 To refer to a variable of the superclass, as in super.hawaii = 50.


 To refer to a method of the superclass, as in super.dragNet().

One of the ways you'll use the super keyword is in the constructor method of a subclass. Because a

subclass inherits all the behavior and attributes of its superclass, you have to associate each constructor
method of that subclass with a constructor method of its superclass. Otherwise, some of the behavior and
attributes might not be set up correctly, and the subclass won't be able to function properly.

To make sure that this happens, the first statement of a subclass constructor method must be a call to a
constructor method of the superclass. This requires the super keyword, as in the following statements:

public ReadFiles(String name, int length) {


super(name,length);
}

This example is the constructor method of a subclass, and it uses super(name,length) to call a

comparable constructor in its superclass.

Note

If you don't use super to call a constructor method in the superclass, the program still might compile and

run successfully. If no superclass constructor is called, Java automatically calls one with no arguments
when the subclass constructor begins. If this superclass constructor doesn't exist or provides unexpected
behavior, errors will result, so it's much better to call a superclass constructor yourself.

Working with Existing Objects

One of the things you have learned about object-oriented programming is how it encourages reuse. If you
develop an excellent spell-checking object for use with one Java programming project, it should be possible
to incorporate that object into another project without modification.

If a Java class is well-designed, it's possible to make that class available for use in other programs. As long
as the class is documented thoroughly, a programmer should be able to work with that class as if it were
part of the official Java language itself.

This is an idea that has great potential for software developers. The more objects available for use in your
programs, the less work you have to do when creating your own software. If there's an excellent spell-
checking object that suits your needs, you can use it instead of writing your own. Ideally, you can even give
your boss a false impression about how long it took to add spell-checking functionality to your project, and
use this extra time to make personal long-distance calls from the office.

The author of this book, like many in his profession, is self-employed and works out of his home. Please
keep this in mind when evaluating his advice on how to conduct yourself in the workplace.
When Java was first introduced, the system of sharing objects was largely an informal one. Programmers
developed their objects to be as independent as possible and protected them against misuse through the
use of private variables and public methods to read and write those variables.

Sharing objects becomes more powerful when there's a standard for developing reusable objects. The
benefits of a standard include the following:

 There's less need to document how an object works, because anyone who knows the standard
already knows a lot about how it functions.

 Development tools can be designed that follow the standard, making it possible to work more
easily with these objects.

 Two objects that follow the standard will be able to interact with each other without special
programming to make them compatible.

The standard for developing reusable objects in Java is called JavaBeans, and each individual object is
called a Bean.

Developing JavaBeans

JavaBeans are Java classes designed specifically for the purpose of being reused. These reusable
classes, which are called software components in many programming languages, are developed under a
standard set of rules.

Developing Beans requires a programming tool in addition to the Software Development Kit. Sun
Microsystems offers two tools that demonstrate the technology, the Bean Builder and JavaBeans
Development Kit,at http://java.sun.com/beans/software.

There are also several programs that make it possible to develop Beans and incorporate them into
programs, including Borland JBuilder, NetBeans, Sun ONE Studio, and IBM VisualAge for Java.

The JavaBeans Development Kit, also called the BDK, includes the BeanBox, a visual tool that is used to
add Beans to a Java program and make those Beans work with each other. The BeanBox, which is a Java
program itself, is shown in Figure 12.2.

Figure 12.2 Using the BeanBox to create a Java program out of several Beans.

In Figure 12.2, the BeanBox is being used to link together three Beans: Two buttons and an animated
Bean that displays the Java mascot, an anthropomorphic cuspid named Duke, juggling some giant beans.
A lot of JavaBeans programming can be accomplished by using a tool like the BeanBox—some projects
can be accomplished entirely with the mouse and no coding of your own classes.

Bean programming is a specialized aspect of Java that's best learned after you have mastered the basics
of the language. However, a beginning programmer can accomplish a lot by working with existing Beans,
so you'll benefit by becoming more familiar with JavaBeans as you learn to program.

You'll be developing skills throughout this book that are directly applicable to JavaBeans programming. A
prime example is encapsulation, which you learned about during the previous hour. Using methods to read
and write the values of a variable is a fundamental part of JavaBeans development.

During the previous hour, you saw how getSeconds() and setSeconds() methods could be used in
a class to read and write a variable called newSeconds:

public int getSeconds() {


return newSeconds;
}

public void setSeconds(int newValue) {


if (newValue > 60)
newSeconds = newValue;
}

If the newSeconds variable is private, these methods are an example of encapsulation. One of the

rules of JavaBeans programming is to limit access to object variables according to the following rules:

 The variable should be private.

 A public method to read the variable should begin with get, end with a name that describes the

variable being read, and return the same type of data as the variable.

 A public method to write the variable should begin with set, end with a name that describes the
variable being written, and return void.

 If there are both reading and writing methods, they should end with the same name to describe the
variable.

The preceding example follows all of these rules with the getSeconds and setSeconds methods.
Because of this, if these methods are part of a Bean, the newSeconds variable can be manipulated

directly within a tool like the BeanBox.


In Figure 12.3, the Properties window shows a seconds property that can be changed from within the
BeanBox. This shows up because a setSeconds() method exists in a Bean that's selected in the main

BeanBox window.

Figure 12.3 Manipulating a Bean's variables with the BeanBox's Properties window.

Much of the work that's done creating JavaBeans is for the benefit of programmers using a development
environment such as the BeanBox. The more a Bean can be customized, the more useful it is.

Following the set and get rules for using an object variable is a first step towards making a class a Bean,

and they demonstrate the kind of programming that JavaBeans requires.

These rules make sense for all object-oriented programming that you do because they present a useful
and safe interface between an object and the other classes that will use it. You'll learn more skills that are
useful in Bean development during Hour 22, "Playing Sound Files."

Workshop: Creating a Subclass

To see an example of inheritance at work, you will create a class called Point3D that represents a point in

three-dimensional space. A two-dimensional point can be expressed with an (x,y) coordinate. Applets use
an (x,y) coordinate system to determine where text and graphics should be displayed. Three-dimensional
space adds a third coordinate, which can be called z.

The Point3D class of objects should do three things:

 Keep track of an object's (x,y,z) coordinate.

 Move an object to a new (x,y,z) coordinate when needed.

 Move an object by a certain amount of x, y, and z values as needed.

Java already has a standard class that represents two-dimensional points; it's called Point. It has two
integer variables called x and y that store a Point object's (x,y) location. It also has a move() method to
place a point at the specified location, and a translate() method to move an object by an amount of x

and y values.

Run your word processor and create a new file called Point3D.java. Enter the text of Listing 12.1 into

the file, and save it when you're done.


Example 12.1. The Full Text of Point3D.java

1: import java.awt.*;
2:
3: public class Point3D extends Point {
4: public int z;
5:
6: public Point3D(int x, int y, int z) {
7: super(x,y);
8: this.z = z;
9: }
10:
11: public void move(int x, int y, int z) {
12: this.z = z;
13: super.move(x, y);
14: }
15:
16: public void translate(int x, int y, int z) {
17: this.z += z;
18: super.translate(x, y);
19: }
20: }

After you compile this file with a Java compiler such as javac, you will have a class you can use in
programs. The Point3D class does not have a main() block statement, so you cannot run it with the
java interpreter.

The Point3D class only has to do work that isn't being done by its superclass, Point. This primarily
involves keeping track of the integer variable z, and receiving it as an argument to the move() method,
translate() method, and Point3D() constructor method.

All of the methods use the keywords super and this. The this statement is used to refer to the current
Point3D object, so this.z = z; in Line 8 sets the object variable z equal to the z value that was sent
as an argument to the method in Line 6.

The super statement refers to the superclass of the current object, Point. It is used to set variables and
call methods that were inherited by Point3D. The statement super(x,y) in Line 7 calls the
Point(x,y) constructor in the superclass, which then sets the (x,y) coordinates of the Point3D object.
Because Point already is equipped to handle the x and y axes, it would be redundant for the Point3D

class of objects to do the same thing.


To test out the Point3D class you have compiled, create a program that uses Point and Point3D

objects and moves them around. Create a new file in your word processor and enter Listing 12.2 into it.
Save the file as TryPoints.java.

Example 12.2. The Full Text of TryPoints.java

1: import java.awt.*;
2:
3: class TryPoints {
4: public static void main(String[] arguments) {
5: Point object1 = new Point(11,22);
6: Point3D object2 = new Point3D(7,6,64);
7:
8: System.out.println("The 2D point is located at (" + object1.x
9: + ", " + object1.y + ")");
10: System.out.println("\tIt's being moved to (4, 13)");
11: object1.move(4,13);
12: System.out.println("The 2D point is now at (" + object1.x
13: + ", " + object1.y + ")");
14: System.out.println("\tIt's being moved -10 units on both the x "
15: + "and y axes");
16: object1.translate(-10,-10);
17: System.out.println("The 2D point ends up at (" + object1.x
18: + ", " + object1.y + ")\n");
19:
20: System.out.println("The 3D point is located at (" + object2.x
21: + ", " + object2.y + ", " + object2.z +")");
22: System.out.println("\tIt's being moved to (10, 22, 71)");
23: object2.move(10,22,71);
24: System.out.println("The 3D point is now at (" + object2.x
25: + ", " + object2.y + ", " + object2.z +")");
26: System.out.println("\tIt's being moved -20 units on the x, y "
27: + "and z axes");
28: object2.translate(-20,-20,-20);
29: System.out.println("The 3D point ends up at (" + object2.x
30: + ", " + object2.y + ", " + object2.z +")");
31: }
32: }
After you compile this file and run it with a Java interpreter, the following output should be displayed:

The 2D point is located at (11, 22)


It's being moved to (4, 13)
The 2D point is now at (4, 13)
It's being moved -10 units on both the x and y axes
The 2D point ends up at (-6, 3)

The 3D point is located at (7, 6, 64)


It's being moved to (10, 22, 71)
The 3D point is now at (10, 22, 71)
It's being moved -20 units on the x, y and z axes
The 3D point ends up at (-10, 2, 51)

Summary

When people talk about the miracle of birth, they're probably not speaking of the way a superclass can give
birth to subclasses or the way behavior and attributes are inherited in a hierarchy of classes.

However, if the real world worked the same way that object-oriented programming does, every grandchild
of Mozart could choose to be a brilliant composer. All descendants of Mark Twain could wax poetic about
Mississippi riverboat life. Every skill your direct ancestors worked to achieve would be handed to you
without an ounce of toil.

On the scale of miracles, inheritance isn't quite up to par with continuing the existence of a species or
getting a good tax break. However, it's an effective way to design software with a minimum of redundant
work.

Another timesaver you may come to rely on are JavaBeans, objects that are ready-made for use in other
programs. Whether you're using Beans that were developed by other programmers or designing your own,
you have one more way to achieve something with fewer ounces of actual toil.

You might also like