Chapter 17

Programming with Objects and Classes

In This Chapter

arrow Programming with class (and with style and finesse)

arrow Making objects from classes

arrow Joining the exclusive “I understand classes and objects” society

Chapters 6, 7, and 8 introduce Java’s primitive types — things like int, double, char, and boolean. That’s great, but how often does a real-world problem deal exclusively with such simple values? Consider an exchange between a merchant and a customer. The customer makes a purchase, which can involve item names, model numbers, credit card info, sales tax rates, and lots of other stuff.

In older computer programming languages, you treat an entire purchase like a big pile of unbundled laundry. Imagine a mound of socks, shirts, and other pieces of clothing. You have no basket, so you grab as much as you can handle. As you walk to the washer, you drop a few things — a sock here and a washcloth there. This is like the older way of storing the values in a purchase. In older languages, there’s no purchase. There are only double values, char values, and other loose items. You put the purchase amount in one variable, the customer’s name in another, and the sales tax data somewhere else. But that’s awful. You tend to drop things on your way to the compiler. With small errors in a program, you can easily drop an amount here and a customer’s name there.

So with laundry and computer programming, you’re better off if you have a basket. The newer programming languages, like Java, allow you to combine values and make new, more useful kinds of values. For example, in Java, you can combine double values, boolean values, and other kinds of values to create something that you call a Purchase. Because your purchase info is all in one big bundle, keeping track of the purchase’s pieces is easier. That’s the start of an important computer programming concept — the notion of object-oriented programming.

Creating a Class

I start with a “traditional” example. The program in Listing 17-1 processes simple purchase data. Two runs of the program are shown in Figure 17-1.

Listing 17-1: Doing It the Old Fashioned Way

import java.util.Scanner;

class ProcessData {

    

    public static void main(String args[]) {

        Scanner myScanner = new Scanner(System.in);

        double amount;

        boolean taxable;

        double total;

        System.out.print(“Amount: “);

        amount = myScanner.nextDouble();

        System.out.print(“Taxable? (true/false) “);

        taxable = myScanner.nextBoolean();

        if (taxable) {

           total = amount * 1.05;

        } else {

            total = amount;

        }

        System.out.print(“Total: “);

        System.out.println(total);

    }

}

Figure 17-1: Processing a customer’s purchase.

9780470371749-fg1701.tif

If the output in Figure 17-1 looks funny, it’s because I do nothing in the code to control the number of digits beyond the decimal point. So in the output, the value $20.00 looks like 20.0. That’s okay. I show you how to fix the problem in Chapter 18.

Reference types and Java classes

The code in Listing 17-1 involves a few simple values — amount, taxable, and total. So here’s the main point of this chapter: By combining several simple values, you can get a single, more useful value. That’s the way it works. You take some of Java’s primitive types, whip them together to make a primitive type stew, and what do you get? You get a more useful type called a reference type. Listing 17-2 has an example.

Listing 17-2: What It Means to Be a Purchase

class Purchase {

    double amount;

    boolean taxable;

    double total;

}

The code in Listing 17-2 has no main method, so Eclipse can compile the code, but you can’t run it. When you choose Run⇒Run As in Eclipse’s main menu, the resulting context menu has no Java Application entry. You can click the tiny Run As button in Eclipse’s toolbar and then select Java Application. But then you get the message box shown in Figure 17-2. Because Listing 17-2 has no main method, there’s no place to start the executing. (In fact, the code in Listing 17-2 has no statements at all. There’s nothing to execute.)

Figure 17-2: The code in Listing 17-2 has no main method.

9780470371749-fg1702.eps

Using a newly defined class

To do something useful with the code in Listing 17-2, you need a main method. You can put the main method in a separate file. Listing 17-3 shows you such a file.

Listing 17-3: Making Use of Your Purchase Class

import java.util.Scanner;

class ProcessPurchase {

    

    public static void main(String args[]) {

        Scanner myScanner = new Scanner(System.in);

        Purchase onePurchase = new Purchase();

        System.out.print(“Amount: “);

        onePurchase.amount = myScanner.nextDouble();

        System.out.print(“Taxable? (true/false) “);

        onePurchase.taxable = myScanner.nextBoolean();

        if (onePurchase.taxable) {

            onePurchase.total = onePurchase.amount * 1.05;

        } else {

            onePurchase.total = onePurchase.amount;

        }

        System.out.print(“Total: “);

        System.out.println(onePurchase.total);

    }

}

The best way to understand the code in Listing 17-3 is to compare it, line by line, with the code in Listing 17-1. In fact, there’s a mechanical formula for turning the code in Listing 17-1 into the code in Listing 17-3. Table 17-1 describes the formula.

Table 17-1 Converting Your Code to Use a Class

In Listing 17-1

In Listing 17-3

double amount; boolean taxable; double total;

Purchase onePurchase = new Purchase();

amount

onePurchase.amount

taxable

onePurchase.taxable

total

onePurchase.total

The two programs (in Listings 17-1 and 17-3) do essentially the same thing, but one uses primitive variables, and the other leans on the Purchase code from Listing 17-2. Both programs have runs like the ones shown back in Figure 17-1.

Running code that straddles two separate files

From Eclipse’s point of view, a project that contains two Java source files is no big deal. You create two classes in the same project, and then you choose Run⇒Run As⇒Java Application. Everything works the way you expect it to work.

The only time things become tricky is when you have two main methods in the one project. This section’s example (Listings 17-2 and 17-3) doesn’t suffer from that malady. But as you experiment with your code, you can easily add classes with additional main methods. You may also create a large application with several starting points.

When a project has more than one main method, Eclipse may prompt you and ask which class’s main method you want to run. But sometimes Eclipse doesn’t prompt you. Instead, Eclipse arbitrarily picks one of the main methods and ignores all the others. This can be very confusing. You add a println call to the wrong main method, and nothing appears in the Console view. Hey, what gives?

You can fix the problem by following these steps:

1. Expand the project’s branch in the Package Explorer.

2. Expand the src folder within the project’s branch.

3. Expand the (default package) branch within the src branch.

The (default package) branch contains .java files.

4. (In Windows:) Right-click the .java file whose main method you want to run. (On a Mac:) Control-click the .java file whose main method you want to run.

5. In the resulting context menu, choose Run AsJava Application.

remember.eps You cannot run a project that has no main method. If you try, you get a message box like the one shown earlier in Figure 17-2.

Why bother?

On the surface, the code in Listing 17-3 is longer, more complicated, and harder to read. But think about a big pile of laundry. It may take time to find a basket and to shovel socks into the basket. But when you have clothes in the basket, the clothes are much easier to carry. It’s the same way with the code in Listing 17-3. When you have your data in a Purchase basket, it’s much easier to do complicated things with purchases.

From Classes Come Objects

The code in Listing 17-2 defines a class. A class is a design plan; it describes the way in which you intend to combine and use pieces of data. For example, the code in Listing 17-2 announces your intention to combine double, boolean, and double values to make new Purchase values.

Classes are central to all Java programming. But Java is called an object-oriented language. Java isn’t called a class-oriented language. In fact, no one uses the term class-oriented language. Why not?

Well, you can’t put your arms around a class. A class isn’t real. A class without an object is like a day without chocolate. If you’re sitting in a room right now, glance at all the chairs in the room. How many chairs are in the room? Two? Five? Twenty? In a room with five chairs, you have five chair objects. Each chair (each object) is something real, something you can use, something you can sit on.

A language like Java has classes and objects. So what’s the difference between a class and an object?

check.png An object is a thing.

check.png A class is a design plan for things of that kind.

For example, how would you describe what a chair is? Well, a chair has a seat, a back, and legs. In Java, you may write the stuff in Listing 17-4.

Listing 17-4: What It Means to Be a Chair

/*

* This is real Java code, but this code

*  cannot be compiled on its own:

*/

class Chair {

    FlatHorizonalPanel seat;

    FlatVerticalPanel back;

    LongSkinnyVerticalRods legs;

}

The preceding code is a design plan for chairs. The code tells you that each chair has three things. The code names the things (seat, back, and legs) and tells you a little bit about each thing. (For example, a seat is a FlatHorizontalPanel.) In the same way, the code in Listing 17-2 tells you that each purchase has three things. The code names the things (amount, taxable, and total) and tells you the primitive type of each thing.

So imagine some grand factory at the edge of the universe. While you sleep each night, this factory stamps out tangible objects — objects that you’ll encounter during the next waking day. Tomorrow you’ll go for an interview at the Sloshy Shoes Company. So tonight, the factory builds chairs for the company’s offices. The factory builds chair objects, as shown in Figure 17-3, from the almost-real code in Listing 17-4.

Figure 17-3: Chair objects from the Chair class.

9780470371749-fg1703.tif

In Listing 17-3, the line

Purchase onePurchase = new Purchase();

behaves like that grand factory at the edge of the universe. Instead of creating chair objects, that line in Listing 17-3 creates a purchase object, as shown in Figure 17-4. That Listing 17-3 line is a declaration with an initialization. Just as the line

int count = 0;

declares the count variable and sets count to 0, the line in Listing 17-3 declares the onePurchase variable and makes onePurchase point to a brand-new object. That new object contains three parts: an amount part, a taxable part, and a total part.

Figure 17-4: An object created from the Purchase class.

9780470371749-fg1704.tif

technicalstuff.eps If you want to be picky, there’s a difference between the stuff in Figure 17-4 and the action of the big bold statement in Listing 17-3. Figure 17-4 shows an object with the values 20.00, true, and 21.00 stored in it. The statement in Listing 17-3 creates a new object, but it doesn’t fill the object with useful values. Getting values comes later in Listing 17-3.

Understanding (or ignoring) the subtleties

Sometimes, when you refer to a particular object, you want to emphasize which class the object came from. Well, subtle differences in emphasis call for big differences in terminology. So here’s how Java programmers use the terminology:

check.png The bold line in Listing 17-3 creates a new object.

check.png The bold line in Listing 17-3 creates a new instance of the Purchase class.

The words object and instance are almost synonymous, but Java programmers never say “object of the Purchase class” (or if they do, they feel funny).

By the way, if you mess up this terminology and say something like “object of the Purchase class,” then no one jumps down your throat. Everyone understands what you mean, and life goes on as usual. In fact, I often use a phrase like “Purchase object” to describe an instance of the Purchase class. The difference between object and instance isn’t terribly important. But it’s very important to remember that the words object and instance have the same meaning. (Okay! They have nearly the same meaning.)

Making reference to an object’s parts

After you’ve created an object, you use dots to refer to the object’s parts. For example, in Listing 17-3, I put a value into the onePurchase object’s amount part with the following code:

onePurchase.amount = myScanner.nextDouble();

Later in Listing 17-3, I get the amount part’s value with the following code:

onePurchase.total = onePurchase.amount * 1.05;

This dot business may look cumbersome, but it really helps programmers when they’re trying to organize the code. In Listing 17-1, each variable is a separate entity. But in Listing 17-3, each use of the word amount is inextricably linked to the notion of a purchase. That’s good.

Creating several objects

After you’ve created a Purchase class, you can create as many purchase objects as you want. For example, in Listing 17-5, I create three purchase objects.

Listing 17-5: Processing Purchases

import java.util.Scanner;

class ProcessPurchasesss {

    

   public static void main(String args[]) {

      Scanner myScanner = new Scanner(System.in);

      Purchase aPurchase;

      for (int count = 0; count < 3; count++) {

         aPurchase = new Purchase();

          System.out.print(“Amount: “);

         aPurchase.amount = myScanner.nextDouble();

         System.out.print(“Taxable? (true/false) “);

         aPurchase.taxable = myScanner.nextBoolean();

         if (aPurchase.taxable) {

            aPurchase.total = aPurchase.amount * 1.05;

         } else {

            aPurchase.total = aPurchase.amount;

         }

         System.out.print(“Total: “);

         System.out.println(aPurchase.total);

         System.out.println();

      }

   }

}

Figure 17-5 has a run of the code in Listing 17-5, and Figure 17-6 illustrates the concept.

Figure 17-5: Running the code in Listing 17-5.

9780470371749-fg1705.tif

Figure 17-6: From one class come three objects.

9780470371749-fg1706.tif

remember.eps To compile the code in Listing 17-5, you must have a copy of the Purchase class in the same project. (The Purchase class is in Listing 17-2.) To copy a class’s code from one project to another, see Chapter 16. (One of that chapter’s sidebars describes the copy-and-paste routine.)

Listing 17-5 has only one variable that refers to purchase objects. (The variable’s name is aPurchase.) The program has three purchase objects because the assignment statement

aPurchase = new Purchase();

is executed three times (once for each iteration of the for loop). Just as you can separate an int variable’s assignment from the variable’s declaration

int count;

count = 0;

you can also separate a Purchase variable’s assignment from the variable’s declaration:

Purchase aPurchase;

for (int count = 0; count < 3; count++) {

    aPurchase = new Purchase();

In fact, after you’ve created the code in Listing 17-2, the word Purchase stands for a brand-new type — a reference type. Java has eight built-in primitive types and has as many reference types as people can define during your lifetime. In Listing 17-2, I define the Purchase reference type, and you can define reference types, too.

Table 17-2 has a brief comparison of primitive types and reference types.

Table 17-2 Java Types

Primitive Type

Reference Type

How it’s created

Built into the language

Defined as a Java class

How many are there

Eight

Indefinitely many

Sample variable declaration

int count;

Purchase aPurchase;

Sample assignment

count = 0;

aPurchase = new Purchase();

Assigning a value to one of its parts

(Not applicable)

aPurchase.amount = 20.00;

Another Way to Think about Classes

When you start learning object-oriented programming, you may think this class idea is a big hoax. Some geeks in Silicon Valley had nothing better to do, so they went to a bar and made up some confusing gibberish about classes. They don’t know what it means, but they have fun watching people struggle to understand it.

Well, that’s not what classes are all about. Classes are serious stuff. What’s more, classes are useful. Many reputable studies have shown that classes and object-oriented programming save time and money.

Even so, the notion of a class can be very elusive. Even experienced programmers — the ones who are new to object-oriented programming — have trouble understanding how an object differs from a class.

Classes, objects, and tables

Because classes can be so mysterious, I’ll expand your understanding with another analogy. Figure 17-7 has a table of three purchases. The table’s title consists of one word (the word “Purchase”), and the table has three column headings — the words “amount,” “taxable,” and “total.” Well, the code in Listing 17-2 has the same stuff — Purchase, amount, taxable, and total. So in Figure 17-7, think of the top part of the table (the title and column headings) as a class. Like the code in Listing 17-2, this top part of the table tells us what it means to be a Purchase. (It means having an amount value, a taxable value, and a total value.)

Figure 17-7: A table of purchases.

9780470371749-fg1707.tif

A class is like the top part of a table. And what about an object? Well, an object is like a row of a table. For example, with the code in Listing 17-5 and the input in Figure 17-5, I create three objects (three instances of the Purchase class). The first object has amount value 20.00, taxable value true, and total value 21.00. In the table, the first row has these three values — 20.00, true, and 21.00, as shown in Figure 17-8.

Figure 17-8: A purchase corresponds to a row of the table.

9780470371749-fg1708.tif

Some questions and answers

Here’s the world’s briefest object-oriented programming FAQ:

check.png Can I have an object without having a class?

No, you can’t. In Java, every object is an instance of a class.

check.png Can I have a class without having an object?

Yes, you can. In fact, almost every program in this book creates a class without an object. Take Listing 17-5, for example. The code in Listing 17-5 defines a class named ProcessPurchasesss. And nowhere in Listing 17-5 (or anywhere else) do I create an instance of the ProcessPurchasesss class. I have a class with no objects. That’s just fine. It’s business as usual.

check.png After I’ve created a class and its instances, can I add more instances to the class?

Yes, you can. In Listing 17-5, I create one instance, then another, and then a third. If I went one additional time around the for loop, I’d have a fourth instance, and I’d put a fourth row in the table of Figure 17-8. With no objects, three objects, four objects, or more objects, I still have the same old Purchase class.

check.png Can an object come from more than one class?

Bite your tongue! Maybe other object-oriented languages allow this nasty class cross-breeding, but in Java, it’s strictly forbidden. That’s one of the things that distinguishes Java from some of the languages that preceded it. Java is cleaner, more uniform, and easier to understand.