From the object user's perspective, they know:
Last time, we talked about adding instance variables to the class definition. This is what it looked like:
// (Incomplete) class definition
public class Rectangle
{
// Instance variables
private int height, width ;
// Constructors
public Rectangle() ;
public Rectangle( int initWidth, int initHeight ) ;
// Method Signatures
public void setWidth( int newWidth ) ;
public void setHeight( int newHeight ) ;
public int getWidth() ;
public int getHeight() ;
public int getPerimeter() ;
public int getArea() ;
public boolean isSquare() ;
}
The instance variables are right at the beginning.
Let's write the method definition for setWidth().
// Method definition for getWidth() public void setWidth( int newWidth ) { // Start of method body width = newWidth ; // Method body } // End of method body
Then, there's the method body, which consists of an open brace, some code, and a close brace. The method body consists of Java code.
This method body is called a scope. I can't easily define scope for now, but it indicates a region where variables are valid.
Within this scope, you have access to the following variables:
// Method definition for setWidth()
public void setWidth( int newWidth )
{
width = newWidth ;
}
There's only one assignment statement. The purpose of this
method is to set the internal instance variable, width,
to the parameter, newWidth.
Recall that the parameter is being provided to us from an object user. If the object user wants the width to be 10, then the parameter variable newWidth is set to 10.
However, parameter variables disappear after the method called. Instance variables do not. So if we want to record this information in the object, we must copy the value from the parameter variable to the instance variable.
Thus, the assignment statement:
width = newWidth ;setHeight should be easy to write.
// Method definition for getWidth()
public int getWidth()
{
return width ;
}
You see a return keyword, followed by an expression.
This is called a return statement.
When Java runs a return statement, it does the following:
// Method definition for getWidth() // println() statement never runs public int getWidth() { return width ; System.out.println( "NEVER GETS HERE" ) ; }For example, this code never prints the message "NEVER GETS HERE". That's because running the return statement exits the method with the return value. There's no reason to put code after a return statement that definitely runs, since they have no purpose.
What if some computation is required to figure out the return value? For example, let's look at the code for getPerimeter().
// Method definition for getPerimeter()
public int getPerimeter()
{
return 2 * ( width + height );
}
The perimeter is twice the width plus twice the height.
A return statement can be an expression, provided the type of the expression is the compatible with the return type. In this case, the type of the expression is int and so is the return type. So, they are compatible.
Do you think that methods with return values can only have a single return statement? Can the method body be more complex?
Yes, it can. You can have several statements. Here's how it looks:
// Alternate method definition for getPerimeter()
public int getPerimeter()
{
int twiceWidth = 2 * width ;
int twiceHeight = 2 * height ;
return twiceWidth + twiceHeight ;
}
This time, we have two declarations, followed by a return
statement. This does the same thing as the previous version of
the method. However, it takes three statements instead of one.
Many would write the first version with the single return statement because it is shorter.
Many method definitions are this simple, but certainly there are method definitions that are quite a bit more complex.
int x = 4 ; rect.setWidth( 2 * x ) ;The method call is: rect.setWidth( 2 * x ). Assume this code appears in main() of a class called RectangleTest.
So, now the method call is: rect.setWidth( 8 ). We are passing 8 to the setWidth method.
public void setWidth( int newWidth ) { width = newWidth ; }
width = newWidth ;In an assignment statement, we evaluate the RHS. The RHS contains newWidth, a parameter variable, which evaluates to 8.
This is then copied to the instance variable, width, which is set to 8, replacing the old value of 10.
Since there are no more statements, we head back to the method call.
Let's try another method call, this time with a return value.
int perim = rect.getPerimeter() ;Assume the width is 5, and the height is 10.
public int getPerimeter() { return 2 * ( width + height ); }We have a single return statement. We evaluate the return expression. This means we evaluate 2 * ( width + height ). width is an instance variable with value 5, as assumed earlier. height is an instance variable with value 10, as assumed earlier.
Plugging those values in, we get 2 * (5 + 10). The final evaluated result is 30. This value is returned.
int perim = rect.getPerimeter() ;A method call with a return value evaluates to the return value. The return value of rect.getPerimeter() is 30. So, we replace the method call by its return value, to get
// rect.getPerimeter() evaluates to 30, in this case int perim = 30 ;So, perim gets the value 30, in the assignment statement.