Section 3.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 remaining 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:
public int getSticks()
{ return nSticks;
}
public int getPlayer()
{ return player;
}
A method's Result Type or Return Type is specified just in front of the MethodName. We want the two methods to return int
values that represent OneRowNim
's instance variables. Therefore, their result types are both declared int
.
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
value depending on whether or not all the sticks have been taken. We can name this method gameOver()
and give it 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:
public boolean gameOver()
{ return (nSticks <= 0);
}
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.
Subsection 3.4.1 Invoking a Method That Returns a Value
When we invoke a method that returns a value, the invocation expression takes on, or is replaced by, the value that is returned. For example, if we execute the statements
OneRowNim game1 = new OneRowNim(11);
int sticksLeft = game1.getSticks();
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:
int sticksLeft = 11;
Principle 3.4.1. Evaluating Method Calls.
A nonvoid method call is an expression that has a value of a particular type. After the method is executed, the method call expression becomes the value returned.
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:
int fewerSticks = game1.getSticks() - 1;
boolean done = game1.gameOver();
System.out.println(game1.getPlayer());
game1.getSticks();
In each statement, the method call can be replaced with the value it returns. 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.
Subsection 3.4.2 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 redundancy is outweighed by the added flexibility of being able to call all three methods.
Principle 3.4.2. EFFECTIVE DESIGN:U sing Redundancy.
Incorporating some redundancy into a class, such as providing more than one way to access the value of an instance variable, makes the class more widely usable.
FigureĀ 3.4.3 provides a UML class diagram of the expanded OneRowNim
class.
OneRowNim
.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() |
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.4.4
The output to the console when this program is run will be:
The game is over is: false The next turn is by player: 1 Sticks remaining: 11
Note that the constructor sets player
to 2, so player
stores the value 1 after one turn.
Trace through the code in the following activity.
Activity 3.4.1.
Click on Show CodeLens and then the Next button to step through the code.
Exercises 3.4.3 Self-Study Exercises
1.
What would these segments of Java code display on the screen?
OneRowNim myGame = new OneRowNim(10,2);
System.out.println(myGame.getPlayer());
System.out.println(2 * myGame.getSticks());
System.out.println(myGame.gameOver());
2.
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. In the active code below or in your own development environment, write a Java method for the OneRowNim
class to get the value stored in nMoves
.
In the active code below or in your own development environment, write a method for the OneRowNim
class called playerOneGoesNext()
that returns a boolean
value. The value returned should be true if and only if player one has the next turn.
3.
Write a get method that returns the value stored in nMoves
. Write a method playerOneGoesNext()
that returns a boolean
value true if player one has the next turn.