Class Methods

It is common sense to take a method and try it; if it fails, admit it frankly and try another. But above all, try something."

Franklin Delano Roosevelt

Though this be madness, yet there is method in't..

William Shakespeare, "Hamlet"

CHAPTER CONTENTS

4.1Introductory Example: Old MacDonald Had a FarmÉ

4.2Getting Started With _Methods

4.3Example: The Volume of a Sphere

4.4Methods: A Summary

4.5Graphic/Internet Java: Raising the Flag

Most people dislike unnecessary work. One way to avoid unnecessary work in programming is to write code that is reusable. One technique for writing reusable code is to store the code to be reused in a method. An object can then reuse the code by invoking the method. This chapter takes a first look at how to write Java methods. We will deliberately keep our examples quite simple so that we can focus on the form of a method, how values are passed to the method, how it is executed, and how values are passed back to the calling method, and how execution returns to the calling method. In the next chapter we will look at how to design and implement methods with more complicated control structures and in Chapter 6 at a different kind of method.

4.1 Introductory Example: Old MacDonald Had a FarmÉ[1]

The childrenÕs song Old MacDonald consists of a series of verses like the following:

Old MacDonald had a farm, E-I-E-I-O

And on this farm he had a cow, E-I-E-I-O

With a moo-moo here and moo-moo there

Here a moo there a moo everywhere a moo-moo

Old MacDonald had a farm, E-I-E-I-O

Old MacDonald had a farm, E-I-E-I-O

And on this farm he had a sheep, E-I-E-I-O

With a baa-baa here and baa-baa there

Here a baa there a baa everywhere a baa-baa

Old MacDonald had a farm, E-I-E-I-O

Old MacDonald had a farm, E-I-E-I-O

And on this farm he had a duck, E-I-E-I-O

With a quack-quack here and quack-quack there

Here a quack there a quack everywhere a quack-quack

Old MacDonald had a farm, E-I-E-I-O

and so on. Our problem is to write a program to generate the verses of this song.

Problem: Old MacDonaldÉ

Write a program that displays the lyrics of Old MacDonald.

One Approach.

Before we begin, it should be apparent that we could write a program that does nothing more than display a very long String containing the songÕs lyrics:

// É

class SimpleOldMacDonald extends Object

{

public static void main(String [] args)

{

Screen theScreen = new Screen();

theScreen.println("\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on his farm he had a cow, E-I-E-I-O"

+ "\nWith a moo-moo here and a moo-moo there"

+ "\nHere a moo there a moo everywhere a moo-moo"

+ "\nOld MacDonald had a farm, E-I-E-I-O\n"

+ "\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on his farm he had a sheep, E-I-E-I-O"

+ "\nWith a baa-baa here and a baa-baa there"

+ "\nHere a baa there a baa everywhere a baa-baa"

+ "\nOld MacDonald had a farm, E-I-E-I-O\n"

+ "\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on his farm he had a duck, E-I-E-I-O"

+ "\nWith a quack-quack here and a quack-quack there"

+ "\nHere a quack there a quack everywhere a quack-quack"

+ "\nOld MacDonald had a farm, E-I-E-I-O\n"

// plus any additional verses

);

}

}

While this would be a correct program, it ignores the structure of the song, which consists of similar verses. Ignoring this structure leads to a great deal of redundant coding effort Ñ of the roughly 40 words in each verse, 32 of them are the same from verse to verse.

Eliminating Redundant Code

The key to eliminating redundant code is to take time at the outset to study the structure of the song and build the lyrics in such a way so as to Òfactor outÓ the words that are common to each verse. As we study the verses, we see that each follows a consistent pattern:

Old MacDonald had a farm, E-I-E-I-O

And on his farm he had a creature, E-I-E-I-O

With a sound-sound here and a sound-sound there

Here a sound there a sound everywhere a sound-sound

Old MacDonald had a farm, E-I-E-I-O

That is, everything is the same from one verse to another except for two ÒvariablesÓ Ð the verseÕs creature, and the sound the creature makes. These items that vary from one verse to another are the parameters of the verse. Since each word can be represented as a String, we can devise a Òverse-buildingÓ method that has two String parameter variables, one named creature and one named sound. The basic form of the method will be as follows:

private static String buildVerse(String creature, String sound)

{

// É statements to build a verse from creature and sound

}

To actually build a verse, the words that each verse has in common can be Òhard-wiredÓ into the method as String literals. The String concatenation operator + can be used to combine these String literals and the parameters into verses, as shown in Figure 4.1.

Figure 4.1 Old MacDonald Had a Farm...

/** OldMacDonald.java displays the lyrics to "Old MacDonald."

* Output: The lyrics of the song.

*/

import ann.easyio.*; // Screen

class OldMacDonald extends Object

{

/** utility method to simplify verse-building

* @params creature, a String; sound, a String

* @return a verse of "Old MacDonald" using creature and sound

*/

private static String buildVerse(String creature, String sound)

{

return "\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on this farm he had a " + creature + ", E-I-E-I-O"

+ "\nWith a " + sound + "-" + sound + " here and a " +

sound + "-" + sound + " there"

+ "\nHere a " + sound + " there a " + sound +

" everywhere a " + sound + "-" + sound

+ "\nOld MacDonald had a farm, E-I-E-I-O\n";

}

public static void main(String [] args)

{

String lyrics = buildVerse("cow", "moo")

+ buildVerse("sheep", "baa")

+ buildVerse("duck", "quack")

// plus any other verses

;

Screen theScreen = new Screen();

theScreen.println(lyrics);

}

}

Sample run:

Old MacDonald had a farm, E-I-E-I-O

And on his farm he had a cow, E-I-E-I-O

With a moo-moo here and a moo-moo there

Here a moo there a moo everywhere a moo-moo

Old MacDonald had a farm, E-I-E-I-O

Old MacDonald had a farm, E-I-E-I-O

And on his farm he had a sheep, E-I-E-I-O

With a baa-baa here and a baa-baa there

Here a baa there a baa everywhere a baa-baa

Old MacDonald had a farm, E-I-E-I-O

Old MacDonald had a farm, E-I-E-I-O

And on his farm he had a duck, E-I-E-I-O

With a quack-quack here and a quack-quack there

Here a quack there a quack everywhere a quack-quack

Old MacDonald had a farm, E-I-E-I-O

The main method builds its lyrics by concatenating together the String values returned by each of the buildVerse() messages. Because it invokes the buildVerse() method, the main method is sometimes described as the caller of the buildVerse() method or the sender of the buildVerse() message. We will use these phrases interchangeably.

The words that are different from one verse to another are the arguments that our main method passes to the buildVerse() method, in order for it to build a particular verse. That is, the message

buildVerse("sheep", "baa")

passes the arguments "sheep" and "baa" to our method. During the execution of this call to the method, parameter creature refers to argument "sheep" and parameter sound refers to the argument "baa". By contrast, the message

buildVerse("duck", "quack")

passes the arguments "duck" and "quack" to our method. During the execution of this call to the method, parameters creature and sound refer to the arguments "duck" and "quack", respectively.

Because it Òfactors outÓ the code that is common to each verse, our buildVerse() method makes it easy to add new verses to the song. For example, the expression

buildVerse("horse", "neigh")

builds and returns the verse:

Old MacDonald had a farm, E-I-E-I-O

And on this farm he had a horse, E-I-E-I-O

With a neigh-neigh here and a neigh-neigh there

Here a neigh there a neigh everywhere a neigh-neigh

Old MacDonald had a farm, E-I-E-I-O

When different parts of a program contain the same code, a method provides a way to extract the common code and encapsulate it in one place, so that code need not be written more than once. A methodÕs parameters provide a means by which different values (called arguments) can be passed into the method.

Methods are the first of several techniques Java provides for writing reusable code. In the following sections, we will learn how to design and build methods.

4.2 Getting Started With Methods

Computing With Formulas

There are many problems whose solutions involve the use of one or more formulas. For example, the speed-calculation problem in Section 1.3 used the formula speed = distance / time; the wage-calculation problem in Section 2.1 used the formula wages = hoursWorkedhourlyRate; the problem in Section 3.1 of computing the amount of energy released by a quantity of matter, used Einstein's equation e = mc2. As these examples demonstrate, writing programs to solve such problems is usually straightforward if we know how to write Java expressions for the formulas.

Computing With Methods

Programs that simply use a formula to compute a value may solve the problem at hand, but the code representing the formula cannot be reused by another program. For example, if some program besides that in Figure 3.1 needed to use EinsteinÕs equation, the equation would have to be recalled and retyped because the equation given in Figure 3.1 cannot be reused by another program (except by physically copying and pasting it, which doesnÕt count).

Methods provide a way to make such equations reusable. Computing with methods is thus to plan for the future Ñ to take a long-term strategic approach Ñ presuming that the method is sufficiently useful to be needed again someday.

Method Design And Coding

As we saw in the previous section, code can be made reusable by defining a method containing that code, with appropriate parameters for those parts of the code that can vary from one use to the next. Definitions of Java methods have the following general form:

Java Method Definition

Form

modifiersreturnType methodName(parameterDeclarations)

{

statements

}

where:

modifiers are Java keywords that describe the method, such as public or private, static, final, and so on;

returnType is the type of value returned by the method or the keyword void if the method does not return a value;

methodName is an identifier that names the method;

parameterDeclarations is a list of parameter declarations, separated by commas; it is omitted if there are no parameters;

statements is a sequence of statements of zero or more statements that define the behavior of the method.

Purpose:

Defines a method. A call to the method causes the arguments to be associated with the method's parameters (if there are any), after which the methodÕs statements are executed. Execution returns to the caller when the method terminates, usually as a result of encountering a return statement. ).

The modifier private means that the method being defined can be used only within the class containing it; that is, only methods within the same class can call it. The modifier public must be given to allow other classes to use the method.

Methods defined with the modifier static are class methods (or static methods). They can be called directly by other methods within the same class by using an expression of the form

methodName(argument-list)

Public class methods can be called from outside the class by sending it a message of the form

ClassName.methodName(argument-list).

Methods without the static modifier are instance methods and cannot be called without first creating an object to which a message can be sent (see Chapter 6).

The first line of a method Ð its modifiers, return-type, name, parentheses and parameter declarationsÐ are sometimes called its heading. The rest of the method (enclosed in curly braces) is called the method's body.

To illustrate, the heading of the method buildVerse() in Figure 4.1 is

private static String buildVerse(String creature, String sound)

The method's name is buildVerse and it has two parameters, creature and sound, both of type String. It's return type is String, which tells us that the method will return a String value. The modifier static specifies that buildVerse() is a class method and the modifier private specifies that it can be called only by other methods within the class (e.g., main()), The method'sbody is

{

return "\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on this farm he had a " + creature + ", E-I-E-I-O"

+ "\nWith a " + sound + "-" + sound + " here and a " +

sound + "-" + sound + " there"

+ "\nHere a " + sound + " there a " + sound +

" everywhere a " + sound + "-" + sound

+ "\nOld MacDonald had a farm, E-I-E-I-O\n";

}

The return Statement

Like buildVerse(), most methods use one or more return statements to transfer control from the method back to the caller. The form of the return statement is as follows:

Java returnStatement

Form

return expression;

where:

return is a Java keyword; and

expression is a valid Java expression (or is omitted) whose type is the same as

(or is compatible with) the methodÕs return-type.

Purpose:

Causes

(i) expression to be evaluated,

(ii) the method to terminate,

(iii) execution to transfer back to the caller, and

(iv) the value of expression to be produced as the value computed by the method. For methods whose return-type is void, expression is omitted and only steps (ii) and (iii) are performed .

Thus, since the return-type of the buildVerse() method in Figure 4.1 is String, the methodÕs return statement contains a String expression:

return "\nOld MacDonald had a farm, E-I-E-I-O"

+ "\nAnd on this farm he had a " + creature + ", E-I-E-I-O"

+ "\nWith a " + sound + "-" + sound + " here and a " +

sound + "-" + sound + " there"

+ "\nHere a " + sound + " there a " + sound +

" everywhere a " + sound + "-" + sound

+ "\nOld MacDonald had a farm, E-I-E-I-O\n";

Methods with any return-type other than void must have at least one returnstatement, and every possible execution of the method must reach a return statement or a compilation error will result.

Methods That Return Nothing. Methods that return nothing to their caller are defined using the return-type void. For example, a main method must be a public class method that returns nothing to its caller, and so every main method has the following form:

public static void main(String [] args)

{

statements

}

Areturnstatement is not required in a method whose return-type isvoid.

Designing and Defining Methods

With just a few minor differences, the steps of object-centered design used to design programs can also be used to design methods. We will illustrate this by designing a method for the mass-to-energy conversion problem from Section 3.1.

Method's Objects. Designing a method for a problem involves the usual steps of describing the problemÕs behavior, objects, and operations. However the list of problem objects is modified slightly for a method. To illustrate, here it is the object list for our mass-to-energy problem:

Description of
Problem Object / Type / Kind / Movement / Name
mass / double / variable / received / m
c / double / constant / none / c
2 / integer / constant / none / none
energy / double / variable / returned / none

Since a method receives values from its caller, and returns values to its caller, an object table for a method has an additional column describing the movement of each object in the problem Ñ received by the method, returned by the method, or neither.

Method Specifications. For design and documentation purposes, it is useful to give a succinct description what a method does. Such a description is called a specification, and usually includes the following items:

What values the method receivesÑ the methodÕs parameters and their types)

Any restrictions or limitations on those values in order for the method to work properly, called a precondition

What values the method returns

Any other effects produced by the method, called a postcondition

To illustrate, a specification for our method to find the amount of energy released by a quantity of matter might appear as follows:

Receive: mass, a double

Precondition: mass > 0

Return: the amount of energy when mass is converted to energy

Method Stubs. As soon as we know a methodÕs specification, we can define a stub for the method, consisting of the method's heading and a pair of empty braces for its body. For the heading, one must remember:

A method parameter must be declared to hold each value the method receives.

The methodÕs return-type is the type of value returned by the method (if any).

Applying this to our example problem, we can build the following stub for our method:

public static double massToEnergy(double m)

{

}

Because we want it to be possible for other programs to use this method, we give it the public modifier. And in order for a main method (or other methods) to use the method without having to first create an object, it must be a class method and so we give it the static modifier. Since the method computes a real value, we make its return type double. We give it the name massToEnergy() to describe what it computes Ñ the parentheses are used to indicate that it is a method and not a variable. It has one parameter m to represent the mass being converted, and since the mass is represented as a real number, the type of this parameter is double.

Locals. Because massToEnergy() will use the formula e = mc2, it needs two values: the parameter m and the speed of light constant C. However, whereas the value of m is passed to the method by the caller, the value C is not and thus will have to be declared inside the method's body.

Named values that are not received from the caller (i.e., that have no movement) should be declared within the method.

Such values are called locals, because they exist only while the method is executing; they are undefined both before and after its execution. (See Potential Pitfall 2 in the Programming Pointers at the end of the chapter.) This has two important consequences:

1.Another method may reuse the name of a local for some other purpose (e.g., to declare a different variable or constant), without causing a conflict.