Section 5 - Locals and Functional Return
5A.5.1 Local Variables in Methods
The words prompt and dblRate in the method getInputAndComputeMonthlyPayment() are variable (or object) identifiers. (prompt is actually a string object, as we learned last week, but we informally call it a variable sometimes.) Up until now, we have had only one method, main(), so the scope of these variables, that is, the place where they can be used, was not an issue: we declared the variable objects at the top of the program and used them whenever and wherever we wanted. Now that we have multiple method definitions, we have to be more careful.
Variables declared inside a method are local to that method, which means their names are known only within that one method. Other methods can declare objects with the same names, but they will have nothing to do with the prompt and dblRate in the method getInputAndComputeMonthlyPayment().
This is one of the most important simple facts about methods.
If the following two methods appear in the same program:
void dog() { int bird; // method statements ... } void cat() { double bird; // method statements ... }
then the two bird objects are distinct and unrelated.
This motivates a question:
If objects in different methods are distinct, how do you design programs so that different methods operate on the same data?
It seems reasonable that we would want a method to calculate a number, and return that number back to main() which would, in turn, pass it on to a second method for further processing. (Excellent question -- what's your name?)
5A.5.2 Returning Values from Methods
There are three ways that information can be transferred between main() and the methods that it calls. This section is devoted to the first of these ways: functional return. Remember - methods are also called functions, so that's where the term functional return arose. Methodal return, just didn't sound right.
You can use functions to return values to the main() through the functional return by taking the following steps:
-
Declare the data type of the return object in the method header. If we want the method to return an int then the header would be written:
If we want it to return a double then it might look like this:
int abalone() { }
Notice that we can have other modifying words like private before the method name in addition to the return type. (We haven't defined private yet, but when we do, this is how it could be used together with the return type.)double abalone() { }
-
Supply a "return" statement in the method, which describes the actual value that is to be sent back, or returned to the main().
The return statement can appear anywhere in the method. For instance, if it appears inside a while loop or if statement, then there would probably be other statements after it.
double abalone() { // method statements ... return 1.020203; // use parens if you want // possibly other method statements ... }
There can be more than one return statement; the first one that is encountered on a given run causes the method to return. The return value can come from a constant, object or even expression:if (pistol == loaded) return 1.020203; // otherwise we continue with statements
However, complex expressions in return statements are not recommended because they make debugging difficult.if (pistol == loaded) return 1.020203; else if (pistol == empty) return x; else if (pistol == broken) return (1.020203 + x)/pistol;
You may be wondering how main() receives and uses this functional return value. When the method is called, it begins executing. When it returns, control passes back to main(). At that point any functional return value replaces the method call. If the method call is inside a larger expression, then this causes the returned value to be used in place of the method call inside that expression.
Examples:
y = cat(); z = (1.5 + cat()) / y; p = (cat() + 1) / (cat() + 2); cat();
In the first example ...
... cat() is called and the value it returns replaces the call cat(). Let's say it returned 1.020203. Then after the method was complete and returned to the main(), the calling statement would be
y = 1.020203;
the value replacing the method call.
In the second example ...
... the same thing happens, but the functional return replaces the cat() which is inside a more complex expression.
In the third example ...
... cat() is called twice in a single statement in the third example. There is no guarantee that the leftmost cat() will be called before the rightmost cat(). But they are separate calls, so the method is entered and exits twice, each time replacing the cat() with the resultant value (which might be different each time it is called!).
In the last example ...
... cat() is called, the functional return value replaces it, and nothing is done with the value. It evaporates. It is not an error to throw away a functional return value, however if you do it always for a particular method, then perhaps you should change its return type to void and not bother supplying a value in its return statement.
If a void method, i.e. a method whose return type is void:
void foo();
has a return statement, then it cannot have a value after the return. Conversely, a non- void method must have a return statement, and it must contain a value.
5A.5.3 Methods Calling Methods
There is no law that says all methods must be called from main(). Up to this point in the lecture, I spoke as if methods were, in fact, called from main(), but they may be called from other methods:
void main() { spaceControl(); } void spaceControl() { float y; y = desk(); } float desk() { float x, y, a; // statements using x and y ... a = x + y; return a; }
We don't always know, by looking at a method definition, from where it will be called. Therefore, rather than assuming that it is main(), we often say that the method is called from and returns to "the client", or "the caller." That client or caller could be main(), but it could also be some other method.