Chapter 12

Functions


CONTENTS

Until now, your programs have been pretty short, each designed to demonstrate a single programming technique. When you start writing real programs, however, you'll quickly discover that they can grow to many pages of code. When programs get long, they also get harder to organize and read. To overcome this problem, professional programmers break their programs down into individual functions, each of which completes a specific and well-defined task.

The Top-Down Approach to Programming

As I said, long programs are hard to organize and read. A full-length program contains many pages of code, and trying to find a specific part of the program in all that code can be tough. You can use modular program-design techniques to solve this problem. Using modular programming techniques, you can break a long program into individual modules, each of which performs a specific task.

In Chapter 4 "Object-Oriented Programming Concepts," you got a quick look at modular program design, which is also known as structured programming. In that chapter, I used the example of cleaning a house as a way to understand the process of breaking tasks up into specific steps. (The only reasonable way to clean my house is to douse it with gasoline and throw in a lighted match, but we won't get into that now.) You'll use that metaphor again here, in preparation for learning about functions.

When cleaning a house, the main task might be called CLEAN HOUSE. Thinking about cleaning an entire house, however, can be overwhelming. So, to make the task easier, you can break it down into a number of smaller steps. These steps might be CLEAN LIVING ROOM, CLEAN BEDROOM, CLEAN KITCHEN, and CLEAN BATHROOM.

After breaking the housecleaning task down into room-by-room steps, you have a better idea of what to do. But cleaning a room is also a pretty big task-especially if it hasn't been done in a while or if you have cats coughing up fur balls all over the place. So why not break each room step down, too? For example, cleaning the living room could be broken down into PICK UP ROOM, DUST AND POLISH, CLEAN FURNITURE, and VACUUM RUG.

After breaking each room's cleaning down into steps, your housecleaning job is organized much like a pyramid, with the general task on the top. As you work your way down the pyramid, from the main task to the room-by-room list and finally to the tasks for each room, the tasks get more and more specific.

Of course, when cleaning a house, you don't usually write a list of steps. If you're an efficient housecleaner, the steps are organized in your mind. (If you clean house like I do, there are only two steps: TURN ON TV and COLLAPSE ON COUCH.) However, when writing a program, which is a more conceptual task, you may not have a clear idea of exactly what needs to be done. This can lead to your being overwhelmed by the project.

Breaking programming tasks down into steps, or modules, is called modular programming. And when you break your program's modules down into even smaller modules-as we did with the task of cleaning a house-you're using a top-down approach to program design. By using top-down programming techniques, you can write any program as a series of small, easy-to-handle tasks. In Java, the basic unit for organizing code in a top-down manner is the function.

Example: Using Functions as Subroutines

When programmers talk about subroutines, they usually mean program modules that return no value to your program. In a way, a subroutine is like a small program within your main program. If you write a housecleaning program, the subroutines in the main module might be called CleanLivingRoom(), CleanBedroom(), CleanKitchen(), and CleanBathroom(). The CleanLivingRoom() subroutine would contain all the steps needed to clean the living room, the CleanBedroom() subroutine would contain all the steps needed to clean a bedroom, and so on.

Of course, it takes an extremely talented programmer to get a computer to clean a house. (If you manage that trick, contact me immediately.) We need a more computer-oriented example. Suppose you want to write a program that displays game instructions on-screen. Listing 12.1 shows one way you might accomplish this task in a Java applet. Figure 12.1 shows what the applet looks like.

Figure 12.1 : This is the Applet13 applet running under Appletviewer.


Listing 12.1  Applet13.java: Printing Instructions in an Applet.

import java.awt.*;

import java.applet.*;



public class Applet13 extends Applet

{

    public void paint(Graphics g)

    {

        g.drawString("Try to guess the number I am", 48, 65);

        g.drawString("thinking of. The number will be", 48, 80);

        g.drawString("between 0 and 100. You have an", 48, 95);

        g.drawString("unlimited number of tries.", 48, 110);

        g.drawString("Good Luck.", 95, 140);

    }

}


Applet13 is about the simplest applet you can write. All it does is display text. The text comprises instructions for playing a simple number game. If you had to sum up in a couple of words the task performed by Applet13's paint() method, you might come up with something like "Draw Instructions," which is an excellent name for a function to handle that task. Listing 12.2 is a new version of the applet that isolates the instruction-display task in its own function. When you run this applet, it looks identical to Applet13.


Listing 12.2  Applet14.java: Placing the Instructions in a Function.

import java.awt.*;

import java.applet.*;



public class Applet14 extends Applet

{

    public void paint(Graphics g)

    {

        DrawInstructions(g);

    }



    void DrawInstructions(Graphics g)

    {

        g.drawString("Try to guess the number I am", 48, 65);

        g.drawString("thinking of. The number will be", 48, 80);

        g.drawString("between 0 and 100. You have an", 48, 95);

        g.drawString("unlimited number of tries.", 48, 110);

        g.drawString("Good Luck.", 95, 140);

    }

}


Now for the million-dollar question: How does this Applet14 work? The program is divided into two functions. The first is the paint() method, which Java calls whenever the applet's display area must be redrawn. In this applet, paint() is at the highest level of your top-down design. That is, no other part of the program calls paint(), but paint() calls functions that are lower in level.

NOTE
You might be confused about the difference between methods, functions, and subroutines. The truth is that they are very similar. Specifically, a method is a function that is part of a class. So, in Applet14, both paint() and DrawInstructions() are methods of the Applet14 class. (They are also functions.) A subroutine is a function that returns no value. That is, it has the word void in front of its name.

The second function in Listing 12.2 is the DrawInstructions() subroutine, which is really just a Java function that returns no value to the calling function (paint(), in this case). DrawInstructions() is one level down from the main program in the top-down design. In paint(), instead of having all the code that's needed to display the instructions, you only have a line that calls the function that handles this task. This makes it easier to see what's going on in paint(). If you need to see more detail, you can always drop down a level in your program and take a look at DrawInstructions().

Defining and Calling Functions

There are two things you must do to use a function in a program. The first thing you must do is define the function, which means that you must write all the program instructions that make up the function, placing the instructions between curly braces. You must also determine what arguments the function must have in order to perform its task. In Applet14, the DrawInstructions() function definition looks like Listing 12.3.


Listing 12.3  LST12_3.TXT: The DrawInstructions( ) Subroutine.

void DrawInstructions(Graphics g)

{

    g.drawString("Try to guess the number I am", 48, 65);

    g.drawString("thinking of. The number will be", 48, 80);

    g.drawString("between 0 and 100. You have an", 48, 95);

    g.drawString("unlimited number of tries.", 48, 110);

    g.drawString("Good Luck.", 95, 140);

}


The first line of Listing 12.3 tells Java the type of value returned from the function, the name of the function, and the arguments that must be sent to the function when it's called. In this case, the type of return value is void, which means the function returns no value. The name of the function is DrawInstructions, and its argument is a Graphics object called g. (Notice that, in the function's first line, you must list both the argument type and argument name.) If you look at the paint() method, you can see that Applet14 calls the DrawInstructions() function like this:


DrawInstructions(g);

This line tells Java that you want to execute the program code in the DrawInstructions() function and that you want to pass the Graphics object g to the function. DrawInstructions() needs access to g because it is the Graphics object that has the drawString() method. Without access to the Graphics object, DrawInstructions() cannot perform its task in the same way that the drawString() method cannot display a string unless you give it the string and the location at which to display the string.

The second thing you must do to use a function is to call the function. When you call a function, program execution jumps to the commands that make up the function. All commands in the function are executed, after which the program returns to the line after the function call.

NOTE
The arguments you place between the parentheses of a function call must be of the same type and in the same order as the arguments given in the function's first line. That is, the call DrawInstructions(g) and the first line of the function, DrawInstructions(Graphics g), match perfectly because the function call sends a Graphics object and the function expects a Graphics object. The names of the arguments, however, don't have to match. For example, the function call DrawInstructions(g) and the function name DrawInstructions(Graphics graph) are still a match. The only difference is that you'd have to refer to graph inside the DrawInstructions() function, rather than to g.

Example: Using Functions to Return Values

In Java, functions are the main way you can break up your programs into modules. But unlike when you used functions as subroutines, some types of functions return a value to the main program. You've used this type of Java function before in this book. The String class' valueOf() method is one. The value it returns is the numerical value of a string containing digits.

You can assign a function's return value to a variable. Suppose you have a function named GetNum() that calculates a number and returns it to your program. A call to the function might look something like this:


int num = GetNum();

The function might look something like Listing 12.4.


Listing 12.4  LST12_4.TXT: An Example of a Function.

int GetNum()

{

    ++value;

    return value;

}


Listing 12.4 shows some of the differences between using functions as subroutines (which return no value) and using functions to return values. While functions being used as subroutines always start with the keyword void, functions that return values start with the keyword int, char, float or whatever type of return value you need. Also, since subroutines return no value, they need no return statement. But as you can see, the GetNum() function returns a value by using the return keyword along with the value to be returned. If you fail to include the return command in the body of a function that returns a value, Java's compiler will give you an error message.

NOTE
Normally, arguments passed into a function are passed by value, which means that a copy of the passed value is given to the function. When you change the value of the argument in the function, you are changing the copy, while the original value stays the same. However, some arguments are passed by reference, which means that the original object is passed to the function. In this case, changing the argument's value in the function changes the original value, too. You learn about passing by reference in Chapter 13, "Arrays."

Example: Putting Functions to Work

Think you understand functions now? The applet you'll build in this example will put your knowledge to the test. Listing 12.5 is the applet's source code, whereas Listing 12.6 is the HTML document that'll load and run the applet. Figure 12.2 shows what the applet looks like when it's running under Appletviewer.

Figure 12.2 : This is the Applet15 applet running under Appletviewer.


Listing 12.5  APPLET15.JAVA: Using Functions in a Java Applet.

import java.awt.*;

import java.applet.*;

import java.lang.Math;



public class Applet15 extends Applet

{

    ///////////////////////////////////////

    // Data fields.

    ///////////////////////////////////////

    TextField textField1;

    int guesses;

    int number;



    ////////////////////////////////////////

    // Overridden methods.

    ////////////////////////////////////////

    public void init()

    {

        textField1 = new TextField(10);

        add(textField1);

        textField1.setText("50");

        guesses = 0;

        number = CreateNumber();

    }



    public void paint(Graphics g)

    {

        DrawInstructions(g);

        int guess = GetGuess();

        ShowMessage(g, guess);

    }



    public boolean action(Event event, Object arg)

    {

        ++guesses;

        repaint();

        return true;

    }



    ////////////////////////////////////////

    // Private methods.

    ////////////////////////////////////////

    void DrawInstructions(Graphics g)

    {

        g.drawString("Try to guess the number I am", 48, 65);

        g.drawString("thinking of. The number will be", 48, 80);

        g.drawString("between 0 and 100. You have an", 48, 95);

        g.drawString("unlimited number of tries.", 48, 110);

        g.drawString("Good Luck.", 95, 140);

    }



    int GetGuess()

    {

        String s = textField1.getText();

        int num = Integer.parseInt(s);

        return num;

    }



    int CreateNumber()

    {

        float n = (float)Math.random();

        number = (int)(n * 100 + 1);

        return number;

    }



    void ShowMessage(Graphics g, int guess)

    {

        String s = "Guesses so far: ";

        s += String.valueOf(guesses);

        g.drawString(s, 80, 170);



        if (guess < number)

            g.drawString("Your guess is too low.", 70, 185);

        else if (guess > number)

            g.drawString("Your guess is too high.", 70, 185);

        else

            g.drawString("You guessed the number!", 65, 185);

    }

}


Tell Java that the program uses classes in the awt package.
Tell Java that the program uses classes in the applet package.
Tell Java that the program uses the lang package's Math class.
Derive the Applet15 class from Java's Applet class.
Declare the class's data fields.
Override the Applet class's init() method.
Create the TextField object.
Add the TextField object to the applet.
Initialize the text in the TextField object to "50."
Initialize the guess counter to zero.
Create the number that the player must guess.
Override the Applet class's paint() method.
Print the game's instructions.
Get the player's guess.
Show the appropriate message based on the guess.
Override the Applet class's action() method.
Increment the guess counter.
Tell Java to redraw the applet's display area.
Tell Java that the action() method finished successfully.
Define the private DrawInstructions() method.
Display the game instructions in the applet.
Define the private GetGuess() method.
Get the text from the TextField object.
Convert the text to an integer.
Return the integer to the calling function.
Define the private CreateNumber() method.
Calculate a random number from 0 to 1.
Convert the random number to an integer between 1 and 100.
Return the random number to the calling function.
Define the private ShowMessage() method.
Display the number of guesses so far.
Display the results of the player's latest guess.

Listing 12.6   APPLET15.htmL: Applet15's HTML Document.

<title>Applet Test Page</title>

<h1>Applet Test Page</h1>

<applet

    code="Applet15.class"

    width=250

    height=250

    name="Applet15">

</applet>


When you run Applet15, the program selects a random numeral from 1 to 100. Your task is to guess the numeral in the least number of tries. You type your guesses into the box at the top of the applet. When the program starts, this box contains the number 50, and the hint at the bottom of the screen tells you whether the number is high or low. Each time you enter a new number, the hint tells you whether the guess is high or low.

Yes, it's true that Applet15 is much larger than the example applets you've used so far in this book, but the program needs to be long in order to accommodate several different functions. By analyzing the program's flow, you can determine whether or not you understand how functions work.

Start with the paint() method. By examining the function calls it contains, you can get a good idea of what the program does. Specifically, the program displays the game's instructions, gets a guess from the user, and then displays a message to the user. If you were only interested in examining the paint() method, you wouldn't have to go any further; the details of how these other functions work are tucked out of your way.

If you wanted to see exactly how the program prints the game's instructions, however, you could find the DrawInstructions() method in the source code. The same is true for the other functions called in the paint() method.

You can see that some of the functions return values and others don't. Similarly, some functions require arguments and others don't. How the function is constructed depends on whether it must calculate and return a value to the program (such as in CreateNumber()) and whether the function requires values from the program in order to perform its task (such as ShowMessage(), which needs the Graphics object and the player's latest guess).

There are probably several lines of Java source code in Listing 12.5 that don't make sense to you right now. The pseudocode section following the listing describes, in general, what the program is doing. You'll learn about many of the details in other chapters. At this point, you only need to worry about being able to follow the function calls.

Summary

Functions enable you to break complicated programs down into easy-to-handle chunks. Moreover, by using a top-down structure, your programs can organize code with functions that start off being general in nature but get more detailed as you work your way deeper into the hierarchy. When a function doesn't return a value (has a return type of void), it is used as a subroutine, which simply performs some task before program execution jumps back to the line after the line that called the function. A function with a return type other than void enables your programs to calculate a value and return the value to the calling function. Either type of function can have one or more arguments, which enable the program to pass values into the function.

Review Questions

  1. What is top-down programming?
  2. How do functions make top-down programming possible?
  3. Do all functions return values?
  4. What are arguments and how are they used?
  5. What is meant by "defining a function"?
  6. How do you return a value from a function?
  7. How do the arguments given in a function call relate to the arguments accepted by the function?
  8. How do you determine how to break a program up into functions?

Review Exercises

  1. Write a function that prints a two-line message to the user.
  2. Write a function that returns the number 1 as an integer.
  3. Write a function that accepts two integer arguments and returns the sum of the arguments.
  4. Modify the function from exercise 3 so that it sums the two arguments, calls yet another function that multiplies the two arguments, sums the product and the original sum, and returns the result. Write the function that performs the multiplication.
  5. Modify Applet15 by adding a function that starts the game over each time the user guesses the number. That is, after the user guesses the number, the program should select a new random number and continue the game. Name the program GuessApplet.java. (You can find the solution to this programming problem in the CHAP12 folder of this book's CD-ROM.)