6. Methods: Communicating with Objects

6.4. Retrieving Information from an Object

The modifications we’ve made to the OneRowNim class allow us to set the instance variables of a OneRowNim object with a constructor, but there is no way for us to retrieve their values other than to use the report() method to write a message to the console. We will want to be able to ask a OneRowNim object to provide us with the number of sticks remain- ing and who plays next when we develop a graphical user interface for OneRowNim in the next chapter. We declared nSticks and player as private variables, so we cannot access them directly. Therefore, we will

 

need accessor methods to get the values of each of the instance variables. Consider the following method definitions:

,,

 

 

 

 

 

J

Recall that a method’s ResultType is specified just in front of the Method- Name. We want the two methods to return int values that represent OneRowNim’s instance variables. Therefore, their result types are both declared int.

Before we discuss how the value that is returned by a method is used

when the method is called, let’s consider one more method definition. Many methods that return a value do a computation rather than simply returning the value of an instance variable. For example, suppose we wish to define a method for the OneRowNim class that will notify the user of an instance of the class whether the game is over. Thus we want a method that, when called, returns a true or false depending on whether or not all the sticks have been taken. gameOver() is a descriptive name of such a method and the method should have a boolean result type. This method should return true when the instance variable nSticks no longer contains a positive int value. Thus we can define:

,,

 

 

J

The expression (nSticks <= 0) evaluates to a false value if nSticks stores a positive value and it evaluates to true otherwise. Thus the value returned is precisely what is required.

 

 

Invoking a Method That Returns a Value

 

 

 

When we invoke a method that returns a value, the invocation expressionRetrieving information

takes on, or is replaced by, the value that is returned. For example, if we execute the statements

,,

 

J

the expression game1.getSticks() will take on the value 11 after the getSticks() method is finished executing. At that point, the second statement above can be treated as if expression game1.getSticks() is

 

replaced with the value 11, which is assigned to sticksLeft. In effect, the second statement is equivalent to the following statement:

,,

 

J

 

We can use a value returned by a method call the same way we use a literal value of the same type. It can be assigned to variables, be part of a numerical expression, or be an argument of another method. All of the following statements involve valid calls of methods that return values:

,,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Redundancy and flexibility


J

In each statement, the method call can be replaced with the value it re- turns. Notice that the last statement is valid but does nothing useful. In Java and some other languages like C and C++, methods that return a value can simply be called without making use of the value returned. This may be useful to do if the method changes the state of instance variables or sends a message to another object or an output device. The method getSticks() does nothing but return the value of nSticks, so simply calling the method accomplishes nothing.

An Expanded OneRowNim Class

Let’s add the new methods that return values to our OneRowNim class. We might note that the report() method from the previous chapter displays the values of nSticks and player in the console window which now could be done by using the methods getSticks() and getPlayer() with System.out.println(). However, calling report() is an easy way to display the values of both instance variables but it cannot provide access to either variable as an int value. So let’s keep all three methods in our class definition. The inconvenience of a small amount of redun- dancy is outweighed by the added flexibility of being able to call all three methods.

 

Figure 3.5 provides a UML class diagram of the expanded OneRowNim

class.

 

 

OneRowNim

nSticks: int

player: int

+ OneRowNim()

+ OneRowNim(in sticks:int)

+ OneRowNim(in sticks:int,in starter:int)

+ takeSticks(in num:int)

+ getSticks():int

+ getPlayer():int

+ gameOver():boolean

+ report()

 

Figure 3.5: A UML class diagram for the expanded OneRowNim.

 

 

Let’s also consider a new main() method to test the new methods of the class. A very short list of statements that call each of the three new methods returning values is given in the main() method in Figure 3.6

 

,,

 

 

 

 

 

 

 

J

Figure 3.6: A main() method that tests the new methods for OneRowNim

 

 

The output to the console when this program is run will be:

,,

 

 

J

Note that the constructor sets player to 2, so player stores the value 1 after one turn.

 

 

 

SELF-STUDY EXERCISES

 

EXERCISE 3.7What would these segments of Java code display on the screen?

,,

 

 

 

J

 

EXERCISE 3.8 Suppose that an int instance variable named nMoves is added to the OneRowNim class that counts the number of moves taken in a One Row Nim game. Write a Java method for the OneRowNim class to get the value stored in nMoves.

 

EXERCISE 3.9 Write a method for the OneRowNim class called playerOneGoesNext() that returns a boolean value. The value re- turned should be true if and only if player one has the next turn.

 

 

 

 

 

 

 

 

Passing a primitive value