All Categories :
Java
Chapter 2
Object-Oriented Programming and Java
by Laura Lemay and Rogers Cadenhead
CONTENTS
Object-oriented programming (OOP) is one of the biggest programming
ideas in recent years-and it's also one of the biggest sources
of consternation for programmers unfamiliar with how it works.
You may fear that years must be spent learning about OOP and how
it makes life easier than other ways to program. The central idea
of object-oriented programming is simple: Organize programs in
ways that echo how things are put together in the real world.
This chapter provides an overview of object-oriented programming
concepts in Java and how they relate to the structure of your
programs. The following topics are covered:
- Classes and objects, and how they relate
to each other
- The two main parts of a class or object:
behavior and attributes
- Class inheritance, and how inheritance
affects the way programs are designed
- Packages and interfaces
If you already are familiar with object-oriented programming,
much of this material will be a review for you. Even if you skim
over the introductory sections, you may want to create the Java
examples in this chapter to get more experience using the language.
Consider, if you will, LEGO building bricks. LEGO bricks, for
those of you who do not spend much time with children, are small
plastic building blocks in various colors and sizes. They have
small round studs on one side that fit snugly into round holes
on other bricks to create larger shapes. With different LEGO pieces
(wheels, engines, hinges, pulleys, and the like), you can make
castles, automobiles, giant robots, or just about anything else
you can imagine. Each LEGO piece is a small object that fits together
with other small objects in specific ways to create other, larger
objects.
Consider another example. You can walk into a computer store and,
with a little expertise and some help, assemble an entire personal
computer system from various components: a motherboard, a CPU
chip, a video card, a hard disk, a keyboard, and so on. Ideally,
when you finish assembling the various self-contained units, you
have a system in which all the units work together to create a
larger system. You can use this larger system to solve the problems
you bought the computer for in the first place.
Internally, each of those computer components might be extremely
complicated and engineered by different companies using different
methods of design. But you don't need to know how each component
works, what every chip on the board does, or how an A gets
sent to your computer when you press the A key. Each component
you use is a self-contained unit, and as the assembler of the
overall system, you are interested only in how the units interact
with each other. Will this video card fit into a slot on the motherboard?
Will this monitor work with this video card? Will each component
speak the right commands to the other components it interacts
with, so that each part of the computer is understood by every
other part? Once you know about the interactions between the components
and can match those interactions, putting together the overall
system is easy.
What do these examples have to do with programming? Everything.
Object-oriented programming is a lot like building structures
from LEGO bricks or assembling a PC. When you use object-oriented
programming, your overall program is made up of lots of different
self-contained components called objects. Each object has a specific
role in the program, and all the objects can talk to each other
in defined ways.
Objects and Classes
Object-oriented programming is modeled on the observation that,
in the real world, objects are made up of many kinds of smaller
objects. However, the capability to combine objects is only one
general aspect of object-oriented programming. Object-oriented
programming provides several other concepts and features to make
the creation and use of objects easier and more flexible. The
most important of these features is the class.
A class is a template for multiple objects with similar
features. Classes embody all the features of a particular set
of objects. When you write a program in an object-oriented language,
you don't define individual objects. You define classes of objects.
For example, you might have a Tree
class that describes the features of all trees (each tree has
branches and roots, grows, and creates chlorophyll). The Tree
class serves as an abstract model for the concept of a tree. To
reach out and grab, or interact with, or cut down a tree, you
must have a concrete instance of that tree. Of course, once you
have a Tree class, you can
create lots of different instances of that tree, and each different
tree instance can have different features (it can be short, tall,
bushy, drop leaves in autumn, and so on), yet still behave like
a tree and be immediately recognizable as one (see Figure 2.1).
Figure 2.1: The Tree Class and Tree instances.
An instance of a class is an actual object of that class.
The class is the general, abstract representation of an object,
and an instance is its concrete representation. So what, precisely,
is the difference between an instance and an object? Nothing,
really. The term object is used more generally, but both
instances and objects are the concrete representations of a class.
In fact, the terms instance and object often are
used interchangeably in OOP terminology. A Tree
instance and a Tree object
are the same thing.
In an example closer to the kind of thing you may want to do with
Java, you can create a class for an on-off switch (an item you
intend to use on dialog boxes and other windows). The LightSwitch
class defines the following features of an on-off switch:
- Its label (if any)
- Its size
- Its appearance
The class also defines how an on-off switch behaves, as follows:
- Whether it needs a single click or a double
click to be activated
- Whether it changes color when clicked
- What it does when it's activated
Once you define the LightSwitch
class, you easily can create instances of that switch-in other
words, LightSwitch objects.
The instances all take on the basic features of a switch as defined
by the class, but each instance can have different appearances
and behavior based on what you want that particular switch to
do. By creating a LightSwitch
class, you don't have to keep rewriting the code for each switch
you want to use in your program. Also, you can reuse the LightSwitch
class to create different kinds of switches as you need them-in
this program and in other programs.
Tip |
If you're used to programming in C, you can think of a class as a way to create a new composite data type that is analogous to using struct and typedef statements in C. Classes, however, can provide much more functionality than just a collection of data, as you'll discover in the rest of this chapter.
|
When you write a Java program, you design and construct a set
of classes. When your program runs, instances of those classes
are created and discarded as needed. Your task, as a Java programmer,
is to create the right set of classes to accomplish what your
program needs to accomplish.
Fortunately, you don't have to start from scratch. The Java environment
comes with a library of classes that implement a lot of the basic
behaviors you need. A class library is a set of classes.
The Java library has classes to handle basic programming tasks
(math functions, arrays, strings, and so on) as well as classes
to handle graphics and networking behavior. In many cases, the
Java class libraries may be sufficient for your needs; all you
have to do in your Java program is to create a single class that
uses the standard class libraries. For complicated Java programs,
however, you may have to create a whole set of classes with defined
interactions between them.
Generally, every class you write in Java is made up of two components:
attributes and behavior. In the following sections, you learn
about each component as it applies to a theoretical class called
Jabberwock. To wrap up this
discussion, you'll create the Java code to implement a representation
of a jabberwock-a dragon-like monster from the Lewis Carroll poem
Jabberwocky.
Attributes of an Object
Attributes are the individual things that differentiate
one object from another and determine the appearance, state, or
other qualities of that object. Consider how a theoretical class
called Jabberwock could be
created. The attributes of a jabberwock might include the following:
- Color: red, orange, yellow
- Sex: male, female
- Appetite: full, hungry
Attributes of an object also can include other information about
its state. For example, you can have features for the jabberwock's
attitude (enraged or calm) or its current health (alive or dead).
Attributes are defined by variables; in fact, you can consider
attributes to be analogous to global variables for the entire
object. Because each instance of a class can have different values
for its variables, each variable is called an instance variable.
Instance variables define the attributes of an object.
The class defines the type of the attribute, and each instance
stores its own value for that attribute.
Each attribute, as the term is used here, has a single corresponding
instance variable; changing the value of a variable changes the
attribute of that object. Instance variables can be set when an
object is created and stay constant throughout the life of the
object, or they can change at will as the program runs.
Class variables apply to the class itself and to all of its instances.
Instance variable values are stored in the instance; class variable
values are stored in the class itself.
How Objects Behave
Behavior is the only way objects can do anything to themselves
or have anything done to them. The behavior of a class determines
what instances of that class do to change their internal state.
Behavior also determines what class instances do when asked to
do something by another class or object. For example, the Jabberwock
class might have some of the following behaviors:
- Get angry
- Calm down
- Eat a peasant
- Skip dinner
- Recuperate
To define an object's behavior, you create methods. Methods
are just like functions in other languages, but they are defined
inside classes. Methods operate on instances of their class. Unlike
C++, Java does not have functions of any kind defined outside
of classes.
Although methods operate within their own class, methods do not
affect only a single object. Objects communicate with each other
using methods. A class or object can call methods in another class
or object to communicate changes in the environment or to ask
that an object change its state.
For example, consider the swordsman in the poem Jabberwocky.
When he attacked the jabberwock with his vorpal blade, here's
what happened:
One, two! One, two! And through and through
The vorpal blade went snicker-snack!
He left it dead, and with its head
He went galumphing back.
In Java, the swordsman could be created as a Knight
object. When the swordsman chops the head off the jabberwock,
it definitely causes a change in the jabberwock's internal state.
The Knight object would use
a method to tell the Jabberwock
object, "I chopped your head off. You're dead."
Just as there are instance and class variables, there are also
instance and class methods. Instance methods (which are so common
they're usually just called methods) apply and operate on an instance
of a class. Class methods apply and operate on a class itself.
Up to now, this chapter has been pretty theoretical. In this section,
however, you create a working example of the Jabberwock
class so that you can see how instance variables and methods are
defined in a class. You also create a Java applet that creates
a new instance of the Jabberwock
class, displays its instance variables, and modifies one of its
instance variables.
Note |
The syntax of this example is not covered in great detail in this chapter. Don't worry too much if you're not completely sure what's going on. All you need to focus on in this example are the basic parts of the Jabberwock class definition.
|
The Jabberwock
Class
We'll name the applet you are creating JabberwockApplet
to distinguish the applet from the Jabberwock
class that it uses. With your Java development software, create
a source file called JabberwockApplet.java.
If you're using the Java Developers Kit, you can create this file
with any text editor that can work with plain text files. If a
project name is required, call it JabberwockApplet.
You start by creating a basic class definition. Enter the following
into your source code editor:
class Jabberwock {
}
Congratulations! You have designed a class. Of course, it doesn't
do much at the moment, but that's a Java class at its simplest.
To make Jabberwock more sophisticated,
create three instance variables for this class. Just below the
class Jabberwock { line,
add the following three lines:
String color;
String sex;
boolean hungry;
These lines create three instance variables. Two, color
and sex, can contain String
objects. (String is part
of that standard class library mentioned earlier.) The third,
hungry, is a boolean
that refers to whether the jabberwock is hungry (true)
or full (false).
Note |
In Java, boolean is a real data type that can have the values true or false. Booleans are not numbers, as they are in C.
|
You can add some behavior to the class by adding methods. There
are all kinds of things a jabberwock can do (claws that catch,
jaws that bite, and so on), but to keep things short, just add
one method-a method to feed the monster. Add the following lines
below the three instance variables in your class definition:
void feedJabberwock(Graphics g, int y) {
if (hungry == true) {
g.drawString("Yum -- a peasant!", 25, y);
hungry = false;
} else
g.drawString("No, thanks -- already ate.", 25, y);
}
// more to come
Tip |
The last line, // more to come, is a comment line. Comments are used for the benefit of programmers looking at source code to figure out what it's doing. Everything from the initial // to the end of the line will be ignored by the compiler. In this case, the comment is being used as a placeholder. You'll replace it soon.
|
The feedJabberwock() method
tests to see whether the jabberwock is hungry (in the line if
(hungry == true) {). If it is hungry, the jabberwock
is fed (much to its delight), and the state of hungry
is changed to false. If the
jabberwock is not hungry, a message is displayed that the monster
already ate. Here's what your program should look like so far:
class Jabberwock {
String color;
String sex;
boolean hungry;
void feedJabberwock(Graphics g, int y) {
if (hungry == true) {
g.drawString("Yum -- a peasant!", 25, y);
hungry = false;
} else
g.drawString("No, thanks -- already ate.", 25, y);
}
// more to come
}
Tip |
The indentation of each part of the class and the insertion of blank lines aren't required for the program to work correctly-the compiler ignores these blanks. Using some form of indentation, however, makes your class definition easier to read. This readability pays dividends when you or another programmer tries later on to figure out what the code is doing. The indentation used here, with instance variables and methods indented from the class definition, is a commonly used style for Java programs. The Java class libraries use a similar indentation. You can choose any indentation style that you like.
|
Before you compile this class, you should add one more method.
The showAtts() method displays
the current values of the instance variables in an instance of
your Jabberwock class. In
the program, delete the comment line //
more to come and replace it with the following:
void showAtts(Graphics g, int y) {
g.drawString("This is a " + sex + " " + color
+ " jabberwock.", 25, y);
if (hungry == true)
g.drawString("The jabberwock is hungry.", 25, y+20);
else
g.drawString("The jabberwock is full.", 25, y+20);
}
The showAtts() method displays
two lines to the screen: the sex
and color of the Jabberwock
object, and whether the monster is hungry. Save your source code
file after adding the showAtts()
method.
At this point, you have a Jabberwock
class and methods that can be used to modify or display its instance
variables. To do something with the class (for example, to create
instances of that class and play with them), you must create the
code for a Java applet that uses the Jabberwock
class.
Listing 2.1 shows the full source code for JabberwockApplet.java.
Return to your text editor and enter lines 1 through 20 above
the source code you already have entered. When you're done, save
the file.
Caution |
It is important to note that Java is case sensitive. In this example, if you enter g.drawstring as a method name instead of g.drawString, it will result as a compiler error because drawstring will not be found in the java.awt.Graphics class.
|
Listing 2.1. JabberwockApplet.java.
1: import java.awt.Graphics;
2:
3: public class JabberwockApplet extends java.applet.Applet {
4:
5: public void paint(Graphics g) {
6: Jabberwock j = new Jabberwock();
7: j.color = "orange";
8: j.sex = "male";
9: j.hungry = true;
10: g.drawString("Calling showAtts ...", 5, 50);
11: j.showAtts(g, 70);
12: g.drawString("Feeding the jabberwock ...", 5, 110);
13: j.feedJabberwock(g, 130);
14: g.drawString("Calling showAtts ...", 5, 150);
15: j.showAtts(g, 170);
16: g.drawString("Feeding the jabberwock ...", 5, 210);
17: j.feedJabberwock(g, 230);
18: }
19: }
20:
21: class Jabberwock {
22: String color;
23: String sex;
24: boolean hungry;
25:
26: void feedJabberwock(Graphics g, int y) {
27: if (hungry == true) {
28: g.drawString("Yum - a peasant!", 25, y);
29: hungry = false;
30: } else
31: g.drawString("No, thanks - already ate.", 25, y);
32: }
33:
34: void showAtts(Graphics g, int y) {
35: g.drawString("This is a " + sex + " " + color
36: + " jabberwock.", 25, y);
37: if (hungry == true)
38: g.drawString("The jabberwock is hungry.", 25, y+20);
39: else
40: g.drawString("The jabberwock is full.", 25, y+20);
41: }
42: }
Before you can test the applet, you must compile it. If you're
using the Java Developers Kit (JDK), the command to compile the
file JabberwockApplet.java
is the following:
javac JabberwockApplet.java
javac is the compiler included
with the JDK. It takes one or more .java
source code files as input and creates class files of compiled
Java bytecode, which have the file extension .class.
When JabberwockApplet.java
is compiled, two .class files
are created: JabberwockApplet.class
and Jabberwock.class.
If the source code has been entered correctly, it should compile
without any errors.
Running the Applet
Although most of the code in the Jabberwock
class definition has been described, the contents of the JabberwockApplet
class in Listing 2.1 are largely new to you. This section more
fully explains the lines that involve the Jabberwock
class to give you an idea of how classes are used.
Line 6, Jabberwock j = new Jabberwock(),
creates a new instance of the Jabberwock
class and stores a reference to it in the variable j.
Remember that you usually do not operate directly on classes in
your Java programs. Instead, you create objects from those classes
and call methods in those objects. Lines 7, 8, and 9 set the instance
variables for the Jabberwock
object j. The color is set
to orange, the sex is set
to male, and the hungry
boolean instance variable
is set to true.
Line 11 calls the showAtts()
method, defined in your Jabberwock
object, with the parameters (g, 70).
(The parameters used here and elsewhere in the program determine
where text will be displayed in the applet. Disregard them for
now.) The showAtts() method
displays the values of the instance variables sex
and color for the Jabberwock
object j. It also displays
the value of the instance variable hungry.
Line 13 calls the feedJabberwock()
method in Jabberwock to feed
object j. Jabberwock
object j is hungry when the
applet starts because hungry
is initially set to true,
so the object eats the food. As you saw in the feedJabberwock()
method described previously, the instance variable hungry
is set to false after the
Jabberwock object eats.
Line 15 calls the showAtts()
method again, displaying the values of the instance variables
for a second time. A change in state for hungry
is shown. Line 17 tries to feed the jabberwock again to see what
happens. Because Jabberwock
object j is no longer hungry,
the object refuses to eat the food.
Now that you have become familiar with what the program is doing,
you should be ready to run JabberwockApplet.
If you're using the Java Developers Kit or some other tool that
does not have the facility to immediately test applets, you must
create a simple Web page that can load the applet. Enter the text
from Listing 2.2 into a file called JabberwockApplet.html.
Using the Java Developers Kit, you can see the output of this
applet by using the following command:
appletviewer JabberwockApplet.html
Listing 2.2. The HTML code of JabberwockApplet.html.
1: <html>
2: <body>
3: <applet code=JabberwockApplet.class height=250 width=300>
4: </applet>
5: </body>
6: </html>
The output should look like the following:
Calling showAtts ...
This is a male orange jabberwock.
The jabberwock is hungry.
Feeding the jabberwock ...
Yum -- a peasant!
Calling showAtts ...
This is a male orange jabberwock.
The jabberwock is full.
Feeding the jabberwock ...
No, thanks -- already ate.
With a basic grasp of classes, objects, methods, and variables,
you have put them together successfully in a Java program. But
this is only part of the story of object-oriented programming.
It's time to learn about the features that make this style of
programming so powerful.
Inheritance, interfaces, and packages are all mechanisms for organizing
classes and class behaviors. The Java class libraries use all
these concepts-and so will the best class libraries you write
for your own programs.
Inheritance
Inheritance is one of the most crucial concepts in object-oriented
programming, and it has a direct effect on how you design and
write Java classes. Inheritance is a powerful mechanism that allows
a class to inherit functionality from an existing class. To create
the new class, you only have to specify how that class is different
from an existing class, and inheritance gives you automatic access
to the existing class.
With inheritance, all classes-those you write, those from other
class libraries that you use, and those from the standard utility
classes as well-are arranged in a strict hierarchy such as the
one shown in Figure 2.2.
Figure 2.2: A class hierarchy.
Each class has a superclass (the class above it in the
hierarchy)-except for the topmost class in the hierarchy. Each
class can have one or more subclasses (classes below it
in the hierarchy). Classes in the hierarchy inherit from classes
above them in the hierarchy.
Subclasses inherit all the methods and variables from their superclasses.
In practical terms, this means that if the superclass defines
behavior your class needs, you don't have to redefine that behavior
or copy that code from some other class. Your class automatically
receives that behavior from its superclass, the superclass gets
behavior from its superclass, and so on, all the way up the hierarchy.
Your class becomes a combination of all the features of the classes
above it in the hierarchy, as well as its own features.
At the top of the Java class hierarchy is the Object
class-all classes inherit from this one superclass. Object
is the most general class in the hierarchy; it defines behavior
inherited by all the classes in the Java class hierarchy. Each
class further down the hierarchy adds more information and becomes
more tailored to a specific purpose. A class hierarchy defines
abstract concepts at the top of the hierarchy, and those concepts
become more concrete the further you go down the chain of subclasses.
Most of the time when you create a new class in Java, you will
want your class to have all the functionality of an existing class
with some new additions or modifications of your own creation.
For example, you may want a version of a LightSwitch
class with images for the switch. To receive all the LightSwitch
functionality, all you have to do is define your class as a subclass
of LightSwitch. Your class
automatically has all the behavior defined in LightSwitch,
and all the behavior defined in the superclasses of LightSwitch.
All you have to worry about are the things that make your new
class different from LightSwitch
itself. The mechanism of defining new classes as the differences
between them and their superclasses is called subclassing.
Subclassing is the creation of a new class that inherits
from an existing class in the class hierarchy. Using subclassing,
you only have to define the differences between your class and
its parent (superclass). The basic behavior is available to your
class through inheritance.
What if your class defines entirely new behavior, and it isn't
really a subclass of another class? Your class also can inherit
directly from Object, which
still allows it to fit neatly into the Java class hierarchy. In
fact, if you create a class definition that doesn't indicate its
superclass in the first line, Java assumes that the new class
is inheriting directly from Object.
The Jabberwock class you
created in the previous section inherited from the Object
class.
Creating a Class Hierarchy
If you're creating a larger set of classes, it makes sense for
your classes not only to inherit from the existing class hierarchy,
but also to make up a hierarchy themselves. Creating this hierarchy
can take some planning beforehand when you're trying to figure
out how to organize your Java code. However, the advantages are
significant:
- When you develop your classes in a hierarchy,
you can put functionality that is common to multiple classes into
superclasses. This arrangement allows that functionality to be
reused repeatedly because each subclass receives that common information
from its superclass.
- Changing or inserting a class further
up in the hierarchy automatically changes the behavior of the
lower classes. There is no need to change or recompile any of
the lower classes because they receive the new information through
inheritance and not by copying any code.
Imagine that you have created a Java class to implement all the
features of a Jabberwock.
It's done, it works, and everything is fine. Your next task is
to create a Java class called Dragon.
Dragon and Jabberwock
have many similar features-both are large monsters that eat peasants.
Both have sharp claws, powerful teeth, and fiery breath. Your
first impulse may be to open up your Jabberwock
class file and copy a lot of the functionality from it into the
new Dragon class.
A far better plan is to factor out the common information for
Dragon and Jabberwock
into a more general class hierarchy. This can be a lot of work
just for the classes Jabberwock
and Dragon, but when you
add classes for Medusa, Yeti,
Sasquatch, and so on, having
common behavior in a reusable superclass significantly reduces
the overall amount of work you have to do.
To design a class hierarchy that serves this purpose, start at
the top with the class Object,
the pinnacle of all Java classes. The most general class to which
Jabberwock and Dragon
both belong might be called Monster.
A monster, generally, is defined as a ferocious creature of some
kind that terrorizes people. In the Monster
class, you define only the behavior that qualifies something as
ferocious and terrifying to people, and nothing more.
Below Monster? How about
two classes: FlyingMonster
and WalkingMonster? FlyingMonster
is different from WalkingMonster
because it can fly (obviously). The behaviors of flying monsters
might include swooping down on prey, carrying people off into
the sky, dropping them from great heights, and so on. Walking
monsters behave differently. Figure 2.3 shows what you have so
far.
Figure 2.3: The basic Monster hierarchy.
Now the hierarchy becomes even more specific. With FlyingMonster,
you may have several subclasses: Mammal,
Reptile, Amphibian,
and so on. As an alternative, you can factor out still more behavior
and have intermediate classes for TwoLegged
and FourLegged monsters,
with different behaviors for each (see Figure 2.4).
Figure 2.4: Two-legged and four-legged flying monsters.
Finally, the hierarchy is done, and you have a place for Jabberwock.
It can be a subclass of reptile, four-legged, flying monsters.
(Actually, going all the way up the class hierarchy, Jabberwock
would be a subclass of reptile, four-legged, flying monster objects,
because FlyingMonster is
a subclass of Object.)
Where do qualities such as sex, color, or appetite come in? They
come in at the place they fit into the class hierarchy most naturally.
If you define sex and color
as instance variables in Monster,
all subclasses will have those variables as well. Remember that
you need to define a feature or a behavior only once in the hierarchy,
and it is automatically reused by each subclass.
How Inheritance Works
How does inheritance work? How is it that instances of one class
automatically receive variables and methods from the classes further
up in the hierarchy? For instance variables, when you create a
new instance of a class, you get a slot for each variable defined
in the current class and a slot for each variable defined in all
its superclasses. In this way, all the classes combine to form
a template for the current object, and each object fills in the
information appropriate to its situation.
Methods operate similarly. New objects have access to all the
method names of the object's class and its superclasses, but method
definitions are chosen dynamically when a method is called. That
is, if you call a method of a particular object, Java first checks
the object's class for the definition of that method. If the method
is not defined in the object's class, Java looks in the superclass
of that class, and so on up the chain until the method definition
is found (see Figure 2.5).
Figure 2.5: How methods are located.
Things get complicated when a subclass defines a method that has
the same name, return type, and arguments as a method defined
in a superclass. In this case, the method definition that is found
first (starting at the bottom of the hierarchy and working upward)
is the one that is executed. Because of this, you can intentionally
create a new method in a subclass to hide a method in the superclass
by defining the new method with the same name, return type, and
arguments as the superclass method. This procedure is called overriding
(see Figure 2.6).
Figure 2.6: Overriding methods.
Single and Multiple Inheritance
Java's form of inheritance, as described in the previous sections,
is called single inheritance. The rule of single inheritance
is that each Java class can have only one superclass (although
any superclass can have multiple subclasses).
In other object-oriented programming languages, such as C++, classes
can have more than one superclass, and they inherit the variables
and methods from all those superclasses. This arrangement is called
multiple inheritance. Multiple inheritance provides enormous
power (classes can be created that encompass just about any imaginable
behavior), but it also significantly complicates class definitions
and the code needed to produce them. Java makes inheritance simpler
by allowing only single inheritance.
Interfaces
Because of single inheritance, any Java class has only a single
superclass. It inherits variables and methods from all superclasses
above it in the hierarchy. This makes subclassing easier to implement
and design, but it also can be restricting-especially when you
have similar behavior that must be duplicated across different
branches of a class hierarchy. Java solves the problem of shared
behavior by using interfaces.
An interface is a collection of method names, without actual
definitions, which indicate that a class has a set of behaviors
in addition to the behaviors it receives from its superclasses.
Although a single Java class can have only one superclass, that
superclass can also implement any number of interfaces. By implementing
an interface, a class provides method definitions for the method
names defined by the interface. If two very different classes
implement the same interface, they both can respond to the same
method calls as defined by that interface. However, what each
class does in response to those method calls can be completely
different.
You don't need to know much about interfaces right now, so don't
panic if this information is confusing. You'll learn more as the
book progresses.
Using Packages
In Java, packages are a way of grouping together related
classes and interfaces. Packages enable groups of classes to be
available only if they are needed. Packages also eliminate potential
conflicts between class names in different groups of classes.
For now, you need to know the following things about packages:
- The class libraries in the JDK are contained
in a package called java.
The classes in the java package
are guaranteed to be available in any Java implementation and
are the only classes guaranteed to be available in any implementation.
The java package contains
other packages for classes that define the language itself, the
input and output classes, some basic networking classes, and the
windowing toolkit functions. Classes in other packages (for example,
those in the sun or netscape
packages) might be available only in specific implementations.
- By default, your Java classes have access
only to the classes in java.lang
(the base language package inside the java
package). To use classes from any other package, you have to either
refer to them explicitly by package name or import them into your
source file.
- To refer to a class within a package,
you list all the packages that the class is contained in followed
by the class name-separated by periods. For example, consider
the Color class. It
is contained in the awt package,
which in turn is contained in the java
package. To refer to the Color
class in your program, you use the notation java.awt.Color.
As a final exercise in this chapter, you will create a subclass
of another class and override some methods. You also will get
a better feel for how packages work.
When you start programming in Java, the most common use of subclassing
is when applets are created. You already relied on subclassing
when you wrote JabberwockApplet.
All applets are subclasses of the class Applet,
which is part of the java.applet
package. By creating a subclass of Applet,
you automatically received behavior from windowing and layout
classes that enabled your applet to be drawn in the right place
and to interact with system operations such as mouse clicks and
key presses.
The BigPalindrome
Applet
To become familiar with subclassing, we'll create an applet called
BigPalindrome, a program
that displays a line of text that reads the same backwards as
forwards (and does so with some panache). Begin developing a new
applet with the filename BigPalindrome.java.
To start the example, first construct the class definition for
the applet. Enter the following class definition:
public class BigPalindrome extends java.applet.Applet {
// placeholder
}
This definition creates a class called BigPalindrome.
Take a look at the phrase extends java.applet.Applet-this
phrase is what makes BigPalindrome
a subclass of the Applet
class. Because the Applet
class is contained in the java.applet
package, as opposed to the java.lang
package, you do not have automatic access to the class. You have
to refer to it explicitly by package and class name.
The other new part of this class definition is the public
keyword. The public keyword
means that your class is available to the Java system at large
once it is loaded. Most of the time, you need to make a class
public only if you want it
to be visible to all other classes in your Java program. However,
applets must be declared as public.
A class definition with nothing in it is pointless-if you don't
add anything new, or override the variables or methods of its
superclasses, why is the new class needed at all? Let's add some
things to make this class different from its superclass.
First, add an instance variable to contain a Font
object. Replace the // placeholder
line with the following:
Font f = new Font("TimesRoman", Font.BOLD, 30);
The f instance variable now
contains a new instance of the class Font,
part of the java.awt package.
This particular font object is a 30-point Times Roman font in
boldface style. If a Font
object is not used and text is displayed, it defaults to 12-point
Times Roman. By using a Font
object, you can change the font of the text displayed in your
applet.
By creating an instance variable to hold this Font
object, you make the object available to all the methods in your
class. Now, you will create a method that uses the object.
Overriding a Method
When you write applets, there are several standard methods defined
in the Applet superclass
that you normally will override in the class of your applet. These
standard methods include methods to initialize the applet, to
start it running, to handle operations such as mouse movements,
and to clean up when the mouse stops running.
One of the methods in the Applet
superclass is the paint()
method, which displays your applet on-screen. The default definition
of paint() does nothing at
all-it's an empty method. By overriding paint(),
you tell the applet what should be drawn on-screen. After the
Font line, enter the following
definition for paint():
public void paint(Graphics g) {
g.setFont(f);
g.setColor(Color.red);
g.drawString("Go hang a salami, I'm a lasagna hog.", 5, 25);
}
Note that this method is declared public,
just as the applet itself was. Unlike the applet, however, the
paint() method is public
because the method it is overriding also is public.
If the method of a superclass is defined as public,
the method to override it also has to be public
or an error will occur when the class is compiled.
Also note that the paint()
method takes a single argument: an instance of the Graphics
class. The Graphics class
provides platform-independent behavior for rendering fonts, colors,
and basic drawing operations. You learn more about the Graphics
class in Chapter 18, "Programming
Applets," when you create more extensive applets.
Inside your paint() method,
you have done the following:
- You told the Graphics
object that the default drawing font will be the one contained
in the instance variable f.
- You told the Graphics
object that the default color is an instance of the Color
class for the color red.
- You told the Graphics
object to draw the palindrome, Go hang
a salami, I'm a lasagna hog., on the applet window
at the x and y
positions of 5 and 25. The string will be rendered in the new
font and color.
Importing a Package
For an applet this simple, no more code seems necessary. However,
something is missing. If you don't know what it is, save the source
file and compile it. You will get a bunch of errors like the following:
BigPalindrome.java:3: Class Font not found in type declaration.
These errors occur because classes such as Font
and Graphics are part of
a package. Remember that the only package you automatically have
access to is java.lang. You
referred to the Applet class
in the first line of the class definition by referring to its
full package name (java.applet.Applet).
Further down in the program, however, you referred to several
other classes as if they already were available.
There are two ways to solve this problem. You can refer to all
external classes by full package name, or you can import the appropriate
class or package at the beginning of your class file. The solution
you choose is mostly a matter of personal choice, but if you refer
to a class in another package numerous times, you may want to
use the import statement
to cut down on the typing required.
In the BigPalindrome example,
import the needed classes: Graphics,
Font, and Color.
All three are part of the java.awt
package. Before the first line of the program, insert the following
three lines:
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
Tip |
You also can import an entire package of public classes by using an asterisk (*) in place of a specific class name. For example, to import all classes in the awt package, you can use the following statement:
import java.awt.*;
|
Listing 2.3 shows the full source code of the BigPalindrome
applet.
Listing 2.3. BigPalindrome.java.
1: import java.awt.Graphics;
2: import java.awt.Font;
3: import java.awt.Color;
4:
5: public class BigPalindrome extends java.applet.Applet {
6:
7: Font f = new Font("TimesRoman", Font.BOLD, 30);
8:
9: public void paint(Graphics g) {
10: g.setFont(f);
11: g.setColor(Color.red);
12: g.drawString("Go hang a salami, I'm a lasagna hog.", 5, 25);
13: }
14: }
Now that the proper classes have been imported into your program,
it should work successfully. Compile the applet, and if you have
to create an HTML page to see it, enter the code in Listing 2.4
into a file called BigPalindrome.html.
Java Developers Kit users can see the output of the applet by
using the following command:
appletviewer BigPalindrome.html
Listing 2.4. The HTML code of BigPalindrome.html.
1: <html>
2: <body>
3: <applet code=BigPalindrome.class height=150 width=500>
4: </applet>
5: </body>
6: </html>
Run the applet and the output should look like Figure 2.7.
Figure 2.7: The output of the BigPalindrome applet.
If this chapter was your first encounter with object-oriented
programming, a lot of the information probably seems both theoretical
and overwhelming at this point. You do not have to fully understand
the information yet because you will be using object-oriented
techniques for the rest of this book. The information will become
more familiar to you as you gain more experience.
One of the biggest hurdles of object-oriented programming is not
necessarily the concepts, it's the names. There is a lot of jargon.
To summarize the material in this chapter, here's a glossary of
terms and concepts that were covered:
class | A template for an object that contains variables to describe the object, and methods to describe how the object behaves. Classes can inherit variables and methods from other classes.
|
Object | A concrete instance of a class-in other words, a real instance that has been created using a class as its template. Multiple instances of the same class have access to the same methods, but they often have different values for their instance variables.
|
Instance | An object made real through the use of a class.
|
Superclass | A class further up the class hierarchy than another class (its subclass). The subclass inherits variables and methods from all superclasses above it in the hierarchy.
|
Subclass | A class further down the class hierarchy than another class (its superclass). When you create a new class to inherit the behavior of another class, the process is called subclassing.
|
Instance method | A method defined in a class that operates on an instance of that class. Instance methods usually are just called methods.
|
class method | A method defined in a class that operates on the class itself and can be called through the class or any of its instances.
|
Instance variable | A variable owned by an individual instance of a class, and whose value is stored in that instance.
|
class variable | A variable owned by the class and all its instances as a whole, and whose value is stored in the class.
|
Interface | A collection of abstract behavior specifications that can be implemented by individual classes.
|
Package | A collection of related classes and interfaces. Classes from packages other than java.lang must be imported explicitly or referred to by their full package names.
|
Contact
reference@developer.com with questions or comments.
Copyright 1998
EarthWeb Inc., All rights reserved.
PLEASE READ THE ACCEPTABLE USAGE STATEMENT.
Copyright 1998 Macmillan Computer Publishing. All rights reserved.