by Laura Lemay
Object-oriented programming (OOP) is one of the biggest programming ideas of recent years, and you might worry that you must spend years learning all about object-oriented programming methodologies and how they can make your life easier than The Old Way of programming. It all comes down to organizing your programs in ways that echo how things are put together in the real world.
Today you'll get an overview of object-oriented programming concepts in Java and how they relate to how you structure your own programs:
If you're already familiar with object-oriented programming, much of today's lesson will be old hat to you. You may want to skim it and go to a movie today instead. Tomorrow, you'll get into more specific details.
Consider, if you will, Legos. Legos, for those who do not spend much time with children, are small plastic building blocks in various colors and sizes. They have small round bits on one side that fit into small round holes on other Legos so that they fit together snugly to create larger shapes. With different Lego parts (Lego wheels, Lego engines, Lego hinges, Lego pulleys), you can put together castles, automobiles, giant robots that swallow cities, or just about anything else you can imagine. Each Lego part is a small object that fits together with other small objects in predefined ways to create other larger objects. That is roughly how object-oriented programming works: putting together smaller elements to build larger ones.
Here's another example. You can walk into a computer store and, with a little background and often some help, assemble an entire pc 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 all the various self-contained units, you have a system in which all the units work together to create a larger system with which you can solve the problems you bought the computer for in the first place.
Internally, each of those components may be vastly complicated and engineered by different companies with different methods of design. But you don't need to know how the component works, what every chip on the board does, or how, when you press the A key, an A gets sent to your computer. As the assembler of the overall system, each component you use is a self-contained unit, and all you are interested in is how the units interact with each other. Will this video card fit into the slots on the motherboard, and will this monitor work with this video card? Will each particular 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 what the interactions are between the components and can match the interactions, putting together the overall system is easy.
What does this have to do with programming? Everything. Object-oriented programming works in exactly this same way. Using object-oriented programming, your overall program is made up of lots of different self-contained components (objects), each of which has a specific role in the program and all of which can talk to each other in predefined ways.
Object-oriented programming is modeled on how, in the real world, objects are often made up of many kinds of smaller objects. This capability of combining objects, however, is only one very general aspect of object-oriented programming. Object-oriented programming provides several other concepts and features to make creating and using objects easier and more flexible, and the most important of these features is classes.
When you write a program in an object-oriented language, you don't define actual objects. You define classes of objects, where a class is a template for multiple objects with similar features. Classes embody all the features of a particular set of objects. For example, you might have a Tree class that describes the features of all trees (has leaves and roots, grows, 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 have to 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 (short, tall, bushy, drops leaves in autumn), while still behaving like and being immediately recognizable as a tree (see Figure 2.1).
Figure 2.1 : The Tree class and several Tree instances.
New Term |
A class is a generic template for a set of objects with similar features. |
An instance of a class is
another word for an actual object. If class is the general (generic)
representation of an object, an instance is its concrete representation.
So what, precisely, is the difference between an instance and
an object? Nothing, really. Object is the more general term, but
both instances and objects are the concrete representation of
a class. In fact, the terms instance and object are often used
interchangeably in OOP lingo. An instance of a tree and a tree
object are both the same thing.
New Term |
An instance is the specific concrete representation of a class. Instances and objects are the same thing. |
What about an example closer to the sort of things you might want
to do in Java programming? You might create a class for the user
interface element called a button. The Button
class defines the features of a button (its label, its size, its
appearance) and how it behaves. (Does it need a single-click or
a double-click to activate it? Does it change color when it's
clicked? What does it do when it's activated?) After you define
the Button class, you can
then easily create instances of that button-that is, button objects-that
all take on the basic features of the button as defined by the
class, but may have different appearances and behavior based on
what you want that particular button to do. By creating a Button
class, you don't have to keep rewriting the code for each individual
button you want to use in your program, and you can reuse the
Button class to create different
kinds of buttons 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 sort of creating a new composite data type by using struct and typedef. Classes, however, can provide much more than just a collection of data, as you'll discover in the rest of today's lesson. |
When you write a Java program, you design and construct a set of classes. Then 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 the very beginning:
The Java environment comes with a standard set of classes (called
a class library)
that implement a lot of the basic behavior you need-not only for
basic programming tasks (classes to provide basic math functions,
arrays, strings, and so on), but also for graphics and networking
behavior. In many cases, the Java class libraries may be enough
so that all you have to do in your Java program is create a single
class that uses the standard class libraries. For complicated
Java programs, you may have to create a whole set of classes with
defined interactions between them.
New Term |
A class library is a collection of classes intended to be reused repeatedly in different programs. The standard Java class libraries contain quite a few classes for accomplishing basic programming tasks in Java. |
Every class you write in Java has two basic features: attributes and behavior. In this section you'll learn about each one as it applies to a theoretical simple class called Motorcycle. To finish up this section, you'll create the Java code to implement a representation of a motorcycle.
Attributes are the individual things that differentiate one object from another and determine the appearance, state, or other qualities of that object. Let's create a theoretical class called Motorcycle. A motorcycle class might include the following attributes and have these typical values:
Attributes of an object can also include information about its state; for example, you could have features for engine condition (off or on) or current gear selected.
Attributes are defined in classes by variables. Those variables'
types and names are defined in the class, and each object can
have its own values for those variables. Because each instance
of a class can have different values for its variables, these
variables are often called instance
variables.
New Term |
An instance variable defines the attributes of the object. Instance variables' types and names are defined in the class, but their values are set and changed in the object. |
Instance variables may be initially set when an object is created and stay constant throughout the life of the object, or they may be able to change at will as the program runs. Change the value of the variable, and you change an object's attributes.
In addition to instance variables, there are also class variables, which apply to the class itself and to all its instances. Unlike instance variables, whose values are stored in the instance, class variables' values are stored in the class itself. You'll learn about class variables later on this week and more specifics about instance variables tomorrow.
A class's behavior determines how an instance of that class operates; for example, how it will "react" if asked to do something by another class or object or if its internal state changes. Behavior is the only way objects can do anything to themselves or have anything done to them. For example, to go back to the theoretical Motorcycle class, here are some behaviors that the Motorcycle class might have:
To define an object's behavior, you create methods,
a set of Java statements that accomplish some task. Methods look
and behave just like functions in other languages but are defined
and accessible solely inside a class. Java does not have functions
defined outside classes (as C++ does).
New Term |
Methods are functions defined inside classes that operate on instances of those classes. |
While methods can be used solely to operate on an individual object, methods are also used between objects to communicate with each other. A class or an object can call methods in another class or object to communicate changes in the environment or to ask that object to change its state.
Just as there are instance and class variables, there are also instance and class methods. Instance methods (which are so common that they're usually just called methods) apply and operate on an instance of a class; class methods apply and operate on the class itself. You'll learn more about class methods later on this week.
Up to this point, today's lesson has been pretty theoretical.
In this section, you'll create a working example of the Motorcycle
class so that you can see how instance variables and methods are
defined in a class in Java. You'll also create a Java application
that creates a new instance of the Motorcycle
class and shows its instance variables.
Note |
I'm not going to go into a lot of detail about the actual syntax of this example here. Don't worry too much about it if you're not really sure what's going on; it will become clear to you later on this week. All you really need to worry about in this example is understanding the basic parts of this class definition. |
Ready? Let's start with a basic class definition. Open the text editor you've been using to create Java source code and enter the following (remember, upper- and lowercase matters):
class Motorcycle { }
Congratulations! You've now created a class. Of course, it doesn't do very much at the moment, but that's a Java class at its very simplest.
First, let's create some instance variables for this class-three of them, to be specific. Just below the first line, add the following three lines:
String make; String color; boolean engineState = false;
Here you've created three instance variables: Two, make
and color, can contain String
objects (a string is the generic term for a series of characters;
String, with a capital S,
is part of that standard class library mentioned earlier). The
third, engineState, is a
boolean variable that refers
to whether the engine is off or on; a value of false
means that the engine is off, and true
means that the engine is on. Note that boolean is lowercase b.
New Term |
A boolean is a value of either true or false. |
Technical Note |
boolean in Java is a real data type that can have the values true or false. Unlike in C, booleans are not numbers. You'll hear about this again tomorrow so that you won't forget. |
Now let's add some behavior (methods) to the class. There are all kinds of things a motorcycle can do, but to keep things short, let's add just one method-a method that starts the engine. Add the following lines below the instance variables in your class definition:
void startEngine() { if (engineState == true) System.out.println("The engine is already on."); else { engineState = true; System.out.println("The engine is now on."); } }
The startEngine() method
tests to see whether the engine is already running (in the part
engineState == true) and,
if it is, merely prints a message to that effect. If the engine
isn't already running, it changes the state of the engine to true
(turning the engine on) and then prints a message. Finally, because
the startEngine() method
doesn't return a value, its definition includes the word void
at the beginning. (You can also define methods to return values;
you'll learn more about method definitions on Day 6, "Creating
Classes and Applications in Java.")
Tip |
Here and throughout this book, whenever I refer to the name of a method, I'll add empty parentheses to the end of the name (for example, as I did in the first sentence of the previous paragraph: "The startEngine() method " This is a convention used in the programming community at large to indicate that a particular name is a method and not a variable. The parentheses are silent. |
With your methods and variables in place, save the program to a file called Motorcycle.java (remember that you should always name your Java source files the same names as the class they define). Listing 2.1 shows what your program should look like so far.
Listing 2.1. The Motorcycle.java file.
1:class Motorcycle { 2: 3: String make; 4: String color; 5: boolean engineState = false; 6: 7: void startEngine() { 8: if (engineState == true) 9: System.out.println("The engine is already on."); 10: else { 11: engineState = true; 12: System.out.println("The engine is now on."); 13: } 14: } 15:}
Tip |
The indentation of each part of the class isn't important to the Java compiler. Using some form of indentation, however, makes your class definition easier for you and other people to read. The indentation used here, with instance variables and methods indented from the class definition, is the style used throughout this book. The Java class libraries use a similar indentation. You can choose any indentation style that you like. |
Before you compile this class, let's add one more method just below the startEngine() method (that is, between lines 14 and 15). The showAtts() method is used to print the current values of all the instance variables in an instance of your Motorcycle class. Here's what it looks like:
void showAtts() { System.out.println("This motorcycle is a " + color + " " + make); if (engineState == true) System.out.println("The engine is on."); else System.out.println("The engine is off."); }
The showAtts() method prints two lines to the screen: the make and color of the motorcycle object and whether the engine is on or off.
Now you have a Java class with three instance variables and two
methods defined. Save that file again, and compile it using one
of the following methods:
Note |
After this point, I'm going to assume you know how to compile and run Java programs. I won't repeat this information after this. |
Windows |
From inside a DOS shell, CD to the directory containing your Java source file, and use the javac command to compile it: |
javac Motorcycle.java
Macintosh |
Drag and drop the Motorcycle.java file onto the Java Compiler icon. |
Salaris |
From a command line, CD to the directory containing your Java source file, and use the javac command to compile it: |
javac Motorcycle.java
When you run this little program using the java or Java Runner programs, you'll get an error. Why? When you run a compiled Java class directly, Java assumes that the class is an application and looks for a main() method. Because we haven't defined a main() method inside the class, the Java interpreter (java) gives you an error something like one of these two errors:
In class Motorcycle: void main(String argv[]) is not defined Exception in thread "main": java.lang.UnknownError
To do something with the Motorcycle class-for example, to create instances of that class and play with them-you're going to need to create a separate Java applet or application that uses this class or add a main() method to this one. For simplicity's sake, let's do the latter. Listing 2.2 shows the main() method you'll add to the Motorcycle class. You'll want to add this method to your Motorcycle.java source file just before the last closing brace (}), underneath the startEngine() and showAtts() methods.
Listing 2.2. The main() method for Motorcycle.java.
1: public static void main (String args[]) { 2: Motorcycle m = new Motorcycle(); 3: m.make = "Yamaha RZ350"; 4: m.color = "yellow"; 5: System.out.println("Calling showAtts..."); 6: m.showAtts(); 7: System.out.println("--------"); 8: System.out.println("Starting engine..."); 9: m.startEngine(); 10: System.out.println("--------"); 11: System.out.println("Calling showAtts..."); 12: m.showAtts(); 13: System.out.println("--------"); 14: System.out.println("Starting engine..."); 15: m.startEngine(); 16:}
With the main() method in place, the Motorcycle class is now an official application, and you can compile it again and this time it'll run. Here's how the output should look:
The first line declares the main()
method. The first line of the main()
method always looks like this; you'll learn the specifics of each
part later this week.
Line 2, Motorcycle m = new Motorcycle();,
creates a new instance of the Motorcycle
class and stores a reference to it in the variable m.
Remember, you don't usually operate directly on classes in your
Java programs; instead, you create objects from those classes
and then call methods in those objects.
Lines 3 and 4 set the instance variables for this Motorcycle
object: The make is now a Yamaha RZ350
(a very pretty motorcycle from the mid-1980s), and the color is
yellow.
Lines 5 and 6 call the showAtts()
method, defined in your Motorcycle
object. (Actually, only 6 does; 5 just prints a message that you're
about to call this method.) The new motorcycle object then prints
out the values of its instance variables-the make
and color as you set in the
previous lines-and shows that the engine is off.
Line 7 prints a divider line to the screen; this is just for prettier
output.
Line 9 calls the startEngine()
method in the motorcycle object to start the engine. The engine
should now be on.
Line 11 prints the values of the instance variables again. This
time, the report should say the engine is now on.
Line 15 tries to start the engine again, just for fun. Because
the engine is already on, this should print the message The
engine is already on.
Listing 2.3 shows the final Motorcycle
class, in case you've been having trouble compiling and running
the one you've got (and remember, this example and all the examples
in this book are available on the CD that accompanies the book):
Now that you have a basic grasp of classes, objects, methods,
variables, and how to put them all together in a Java program,
it's time to confuse you again. Inheritance, interfaces, and packages
are all mechanisms for organizing classes and class behaviors.
The Java class libraries use all these concepts, and the best
class libraries you write for your own programs will also use
these concepts.
Inheritance is one of the most crucial concepts in object-oriented
programming, and it has a very direct effect on how you design
and write your Java classes. Inheritance is a powerful mechanism
that means when you write a class you only have to specify how
that class is different from some other class; inheritance will
give you automatic access to the information contained in that
other 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 (see Figure
2.2). Each class has a superclass (the class above it in the hierarchy),
and each class can have one or more subclasses (classes below
that class in the hierarchy). Classes further down in the hierarchy
are said to inherit from
classes further up in the hierarchy.
Figure 2.2 : A class hierarchy.
Subclasses inherit all the methods and variables from their superclasses-that
is, in any particular class, if the superclass defines behavior
that your class needs, you don't have to redefine it or copy that
code from some other class. Your class automatically gets that
behavior from its superclass, that 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.
At the top of the Java class hierarchy is the class Object;
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 Java. Each class further down
in the hierarchy adds more information and becomes more tailored
to a specific purpose. In this way, you can think of a class hierarchy
as defining very abstract concepts at the top of the hierarchy
and those ideas becoming more concrete the farther down the chain
of superclasses you go.
Most of the time when you write new Java classes, you'll want
to create a class that has all the information some other class
has, plus some extra information. For example, you may want a
version of a Button with
its own built-in label. To get all the Button
information, all you have to do is define your class to inherit
from Button. Your class will
automatically get all the behavior defined in Button
(and in Button's superclasses),
so all you have to worry about are the things that make your class
different from Button itself.
This mechanism for defining new classes as the differences between
them and their superclasses is called subclassing.
Subclassing involves creating
a new class that inherits from some other class in the class hierarchy.
Using subclassing, you only need to define the differences between
your class and its parent; the additional behavior is all available
to your class through inheritance.
What if your class defines an entirely new behavior and isn't
really a subclass of another class? Your class can also 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 automatically assumes you're
inheriting from Object. The
Motorcycle class you created
in the previous section inherited from Object.
If you're creating a larger set of classes for a very complex
program, it makes sense for your classes not only to inherit from
the existing class hierarchy, but also to make up a hierarchy
themselves. This may take some planning beforehand when you're
trying to figure out how to organize your Java code, but the advantages
are significant once it's done:
For example, let's go back to that Motorcycle
class and pretend you created a Java program to implement all
the features of a motorcycle. It's done, it works, and everything
is fine. Now, your next task is to create a Java class called
Car.
Car and Motorcycle
have many similar features-both are vehicles driven by engines.
Both have transmissions, headlamps, and speedometers. So your
first impulse may be to open your Motorcycle
class file and copy over a lot of the information you already
defined into the new class Car.
A far better plan is to factor out the common information for
Car and Motorcycle
into a more general class hierarchy. This may be a lot of work
just for the classes Motorcycle
and Car, but once you add
Bicycle, Scooter,
Truck, and so on, having
common behavior in a reusable superclass significantly reduces
the amount of work you have to do overall.
Let's design a class hierarchy that might serve this purpose.
Starting at the top is the class Object,
which is the root of all Java classes. The most general class
to which a motorcycle and a car both belong might be called Vehicle.
A vehicle, generally, is defined as a thing that propels someone
from one place to another. In the Vehicle
class, you define only the behavior that enables someone to be
propelled from point a to point b, and nothing more.
Below Vehicle? How about
two classes: PersonPoweredVehicle
and EnginePoweredVehicle?
EnginePoweredVehicle is different
from Vehicle because it has
an engine, and the behaviors might include stopping and starting
the engine, having certain amounts of gasoline and oil, and perhaps
the speed or gear in which the engine is running. Person-powered
vehicles have some kind of mechanism for translating people motion
into vehicle motion-pedals, for example. Figure 2.3 shows what
you have so far.
Figure 2.3 : The basic vehicle hierarchy.
Now let's become even more specific. With EnginePoweredVehicle,
you might have several classes: Motorcycle,
Car, Truck,
and so on. Or you can factor out still more behavior and have
intermediate classes for TwoWheeled
and FourWheeled vehicles,
with different behaviors for each (see Figure 2.4).
Figure 2.4 : Two-wheeled and four-wheeled vehicles.
Finally, with a subclass for the two-wheeled engine-powered vehicles,
you can have a class for motorcycles. Alternatively, you could
additionally define scooters and mopeds, both of which are two-wheeled
engine-powered vehicles but have different qualities from motorcycles.
Where do qualities such as make or color come in? Wherever you
want them to go-or, more usually, where they fit most naturally
in the class hierarchy. You can define the make and color on Vehicle,
and all the subclasses will have those variables as well. The
point to remember is that you have to define a feature or a behavior
only once in the hierarchy; it's automatically reused by each
subclass.
How does inheritance work? How is it that instances of one class
can automatically get 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 for each variable defined in all its superclasses. In
this way, all the classes combine to form a template for the current
object, and then each object fills in the information appropriate
to its situation.
Methods operate similarly: New objects have access to all the
method names of its class and its superclasses, but method definitions
are chosen dynamically when a method is called. That is, if you
call a method on a particular object, Java first checks the object's
class for the definition of that method. If it's not defined in
the object's class, it looks in that class's superclass, 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 signature (name, number, and type of arguments) as a
method defined in a superclass. In this case, the method definition
that is found first (starting at the bottom and working upward
toward the top of the hierarchy) is the one that is actually executed.
Therefore, you can intentionally define a method in a subclass
that has the same signature as a method in a superclass, which
then "hides" the superclass's method. This is called
overriding a method. You'll
learn all about methods on Day 7, "More About Methods."
Figure 2.6 : Overriding methods.
Java's form of inheritance, as you learned in the previous sections,
is called single inheritance.
Single inheritance means that each Java class can have only one
superclass (although any given superclass can have multiple subclasses).
In other object-oriented programming languages, such as C++, classes
can have more than one superclass, and they inherit combined variables
and methods from all those classes. This is called multiple
inheritance. Multiple inheritance can provide enormous
power in terms of being able to create classes that factor just
about all imaginable behavior, but it can also significantly complicate
class definitions and the code to produce them. Java makes inheritance
simpler by being only singly inherited.
There are two remaining concepts to discuss here: packages and
interfaces. Both are advanced topics for implementing and designing
groups of classes and class behavior. You'll learn about both
interfaces and packages on Day 16, "Packages and Interfaces,"
but they are worth at least introducing here.
Recall that each Java class has only a single superclass, and
it inherits variables and methods from that superclass and all
its superclasses. Although single inheritance makes the relationship
between classes and the functionality those classes implement
easy to understand and to design, it can also be somewhat restrictive-in
particular, when you have similar behavior that needs to be duplicated
across different "branches" of the class hierarchy.
Java solves this problem of shared behavior by using the concept
of interfaces, which collect method names into one place and then
allow you to add those methods as a group to the various classes
that need them. Note that interfaces contain only method names
and interfaces (arguments, for example), not actual definitions.
Although a single Java class can have only one superclass (due
to single inheritance), that class can also implement any number
of interfaces. By implementing an interface, a class provides
method implementations (definitions) for the method names defined
by the interface. If two very disparate classes implement the
same interface, they can both respond to the same method calls
(as defined by that interface), although what each class actually
does in response to those method calls may be very different.
You don't need to know very much about interfaces right now. You'll
learn more as the book progresses, so if all this is very confusing,
don't panic!
The final new Java concept for today is packages. Packages
in Java are a way of grouping together related classes and interfaces
in a single library or collection. Packages enable modular groups
of classes to be available only if they are needed and eliminate
potential conflicts between class names in different groups of
classes.
You'll learn all about packages, including how to create and use
them, in Week 3. For now, there are only a few things you need
to know:
To finish up today, let's create a class that is a subclass of
another class and override some methods. You'll also get a basic
feel for how packages work in this example.
Probably the most typical instance of creating a subclass, at
least when you first start programming in Java, is creating an
applet. All applets are subclasses of the class Applet
(which is part of the java.applet
package). By creating a subclass of Applet,
you automatically get all the behavior from the window toolkit
and the layout classes that enable your applet to be drawn in
the right place on the page and to interact with system operations,
such as keypresses and mouse clicks.
In this example, you'll create an applet similar to the Hello
World applet from yesterday, but one that draws the Hello
string in a larger font and a different color. To start this example,
let's first construct the class definition itself. Let's go to
your text editor, and enter the following class definition:
Here, you're creating a class called HelloAgainApplet.
Note the part that says extends java.applet.Applet-that's
the part that says your applet class is a subclass of the Applet
class. Note that because the Applet
class is contained in the java.applet
package, you don't have automatic access to that class, and you
have to refer to it explicitly by package and class name.
The other part of this class definition is the public
keyword. Public 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 the other classes in your
Java program, but applets, in particular, must be declared to
be public. (You'll learn more about public
classes in Week 3.)
A class definition with nothing in it doesn't really have much
of a point; without adding or overriding any of its superclasses'
variables or methods, there's no reason to create a subclass at
all. Let's add some information to this class, inside the two
enclosing braces, to make it different from its superclass.
First, add an instance variable to contain a Font
object:
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 Times Roman font, boldface, 36 points high. In the previous
Hello World applet, the font used for the text was the default
font: 12-point Times Roman. Using a Font
object, you can change the font of the text you draw in your applet.
By creating an instance variable to hold this font object, you
make it available to all the methods in your class. Now let's
create a method that uses it.
When you write applets, there are several "standard"
methods defined in the applet superclasses that you will commonly
override in your applet class. These include methods to initialize
the applet, to make it start running, to handle operations such
as mouse movements or mouse clicks, or to clean up when the applet
stops running. One of those standard methods is the paint()
method, which actually displays your applet onscreen. The default
definition of paint() doesn't
do anything-it's an empty method. By overriding paint(),
you tell the applet just what to draw on the screen. Here's a
definition of paint():
There are two things to know about the paint()
method. First, note that this method is declared public,
just as the applet itself was. The paint()
method is actually public
for a different reason-because the method it's overriding is also
public. If a superclass's
method is defined as public,
your override method also has to be public,
or you'll get an error when you compile the class.
Second, 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 behavior for drawing basic lines and shapes. You'll learn
a lot more about the Graphics
class in Week 2, when you create more extensive applets.
Inside your paint() method,
you've done three things:
For an applet this simple, this is all you need to do. Here's
what the applet looks like so far:
If you've been paying close attention, you'll notice that something
is wrong with this example up to this point. If you don't know
what it is, try saving this file (remember, save it to the same
name as the class: HelloAgainApplet.java)
and compiling it. You should get a bunch of errors similar to
this one:
Why are you getting these errors? Because the classes you're referring
to in this class, such as Graphics
and Font, are part of a package
that isn't available by default. Remember that the only package
you have access to automatically in your Java programs 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 on in the program, however, you referred to all kinds
of other classes as if they were available. The compiler catches
this and tells you that you don't have access to those other classes.
There are two ways to solve this problem: Refer to all external
classes by full package name or import the appropriate class or
package at the beginning of your class file. Which one you choose
to do is mostly a matter of choice, although if you find yourself
referring to a class in another package lots of times, you may
want to import it to cut down on the amount of typing.
In this example, you'll import the classes you need. There are
three of them: Graphics,
Font, and Color.
All three are part of the java.awt
package. Here are the lines to import these classes. These lines
go at the top of your program, before the actual class definition:
Now, with the proper classes imported into your program, HelloAgainApplet.java
should compile cleanly to a class file. Listing 2.4 shows the
final version to double-check.
To test it, create an HTML file with the <APPLET>
tag as you did yesterday. Here's an HTML file to use:
For this HTML example, your Java class file is in the same directory
as this HTML file. Save the file to HelloAgainApplet.html
and fire up your Java-enabled browser or the Java applet viewer.
Figure 2.7 shows the result you should be getting (the "Hello
Again!" string is red).
Figure 2.7 : The HelloAgain
applet.
If this is your first encounter with object-oriented programming,
a lot of the information in this lesson is going to seem really
theoretical and overwhelming. Fear not-the further along in this
book you get, and the more Java classes and applications you create,
the easier it is to understand.
One of the biggest hurdles of object-oriented programming is not
necessarily the concepts; it's their names. OOP has lots of jargon
surrounding it. To summarize today's material, here's a glossary
of terms and concepts you learned today:
Most of the time, you'll use instance variables and methods. You'll learn more about class variables and methods later this week.
Calling showAtts...
This motorcycle is a yellow Yamaha RZ350
The engine is off.
--------
Starting engine...
The engine is now on.
--------
Calling showAtts...
This motorcycle is a yellow Yamaha RZ350
The engine is on.
--------
Starting engine...
The engine is already on.
Analysis
The contents of the main() method are all going to look very new to you, so let's go through it line by line so that you at least have a basic idea of what it does (you'll get details about the specifics of all of this tomorrow and the day after).
Listing 2.3. The final version of Motorcycle.java.
1: class Motorcycle {
2:
3: String make;
4: String color;
5: boolean engineState;
6:
7: void startEngine() {
8: if (engineState == true)
9: System.out.println("The engine is already on.");
10: else {
11: engineState = true;
12: System.out.println("The engine is now on.");
13: }
14: }
15:
16: void showAtts() {
17: System.out.println("This motorcycle is a "
18: + color + " " + make);
19: if (engineState == true)
20: System.out.println("The engine is on.");
21: else System.out.println("The engine is off.");
22: }
23:
24: public static void main (String args[]) {
25: Motorcycle m = new Motorcycle();
26: m.make = "Yamaha RZ350";
27: m.color = "yellow";
28: System.out.println("Calling showAtts...");
29: m.showAtts();
30: System.out.println("------");
31: System.out.println("Starting engine...");
32: m.startEngine();
33: System.out.println("------");
34: System.out.println("Calling showAtts...");
35: m.showAtts();
36: System.out.println("------");
37: System.out.println("Starting engine...");
38: m.startEngine();
39: }
40:}
Inheritance, Interfaces, and Packages
Inheritance
New Term
Inheritance is a concept in object-oriented programming where all classes are arranged in a strict hierarchy. Each class in the hierarchy has superclasses (classes above it in the hierarchy) and any number of subclasses (classes
below it in the hierarchy). Subclasses inherit attributes and behavior from their superclasses.
New Term
Subclassing is the process of creating a new class that inherits from some other already-existing class.
Creating a Class Hierarchy
How Inheritance Works
New Term
Overriding a method is creating a method in a subclass that has the same signature (name, number, and type of arguments) as a method in a superclass. That new method then hides the superclass's method (see Figure 2.6).
Single and Multiple Inheritance
Interfaces and Packages
New Term
An interface is a collection of method names, without definitions, that can be added to classes to provide additional behavior not included with those methods the class defined itself or inherited from its superclasses.
Creating a Subclass
public class HelloAgainApplet extends java.applet.Applet {
}
Font f = new Font("TimesRoman", Font.BOLD, 36);
public void paint(Graphics g) {
g.setFont(f);
g.setColor(Color.red);
g.drawString("Hello again!", 5, 40);
}
public class HelloAgainApplet extends java.applet.Applet {
Font f = new Font("TimesRoman",Font.BOLD,36);
public void paint(Graphics g) {
g.setFont(f);
g.setColor(Color.red);
g.drawString("Hello again!", 5, 40);
}
}
HelloAgainApplet.java:7: Class Graphics not found in type declaration.
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 the classes in the awt package, you can use this line:
import java.awt.*;
Listing 2.4. The final version of HelloAgainApplet.java.
1:import java.awt.Graphics;
2:import java.awt.Font;
3:import java.awt.Color;
4:
5:public class HelloAgainApplet extends java.applet.Applet {
6:
7: Font f = new Font("TimesRoman",Font.BOLD,36);
8:
9: public void paint(Graphics g) {
10: g.setFont(f);
11: g.setColor(Color.red);
12: g.drawString("Hello again!", 5, 40);
13: }
14:}
<HTML>
<HEAD>
<TITLE>Another Applet</TITLE>
</HEAD>
<BODY>
<P>My second Java applet says:
<BR><APPLET CODE="HelloAgainApplet.class" WIDTH=200 HEIGHT=50>
</APPLET>
</BODY>
</HTML>
Summary
class:
A template for an object, which contains variables and methods
representing behavior and attributes. Classes can inherit variables
and methods from other classes.
class method: A method
defined in a class, which operates on the class itself and can
be called via the class or any of its instances.
class variable:
A variable that is "owned" by the class and all
its instances as a whole and is stored in the class.
instance:
The same thing as an object; each object is an instance of some
class.
instance method:
A method defined in a class, which operates on an instance of
that class. Instance methods are usually called just methods.
instance variable:
A variable that is owned by an individual instance and
whose value is stored in the instance.
interface:
A collection of abstract behavior specifications that individual
classes can then implement.
object:
A concrete instance of some class. Multiple objects that are instances
of the same class have access to the same methods, but often have
different values for their instance variables.
package:
A collection of classes and interfaces. Classes from packages
other than java.lang must
be explicitly imported or referred to by full package name.
subclass:
A class lower in the inheritance hierarchy than its parent, the
superclass. When you create a new class, it's often called subclassing.
superclass:
A class further up in the inheritance hierarchy than its child,
the subclass.
Q&A
Methods are effectively functions that are defined inside classes. If they look like functions and act like functions, why aren't they called functions?
Some object-oriented programming languages do call them functions (C++ calls them member functions). Other object-oriented languages differentiate between functions inside and outside a body of
a class or object, where having separate terms is important to understanding how each works. Because the difference is relevant in other languages and because the term method is now in such common use in object-oriented technology, Java uses the word as
well.
I understand instance variables and methods, but not the idea of class variables and methods.
Most everything you do in a Java program will be with objects. Some behaviors and attributes, however, make more sense if they are stored in the class itself rather than in the object. For
example, to create a new instance of a class, you need a method that is defined and available in the class itself. (Otherwise, how can you create an object? You need an object to call the method, but you don't have an object yet.) Class variables, on the
other hand, are often used when you have an attribute whose value you want to share with all the instances of a class.