Unit 04 Component Client View Methods
Unit 04 Component Client View Methods
Unit 4 - 1
applied to a variable, and we will continue to use the clock example. When thats done,
well have a good understanding of how components are described to clients.
Unit 4 - 2
Describing Methods An Example
The first method well look at is a method that can be used to set the hours of a clock
variable. The figure titled Client Description of setHours for AMPMClock provides
the description for this method.
// CONTINUATION OF AMPMClock
Parameters:
method contract
Updates:
Updates lists the parameters
that may be modified
this.hours
// AMPMClock TO BE CONTINUED...
There is quite a bit to understand in this little method description, so well take our time
and discuss it carefully.
Unit 4 - 3
The Method Header
The line
void setHours(int newHours)
is called the method header or method signature or method prototype. It specifies the
name of the method and the parameter list. The name is setHours, appearing just after
the keyword void. (The keyword void indicates that this method is a procedure, i.e., it
does not return a value explicitly.) In this case the parameter list contains a single
parameter and has the following structure:
int newHours
type of name of
parameter parameter
Note that there is no code here. The actual implementation of the method setHours
will appear in some other component (a class). This is just what we want, since the
component AMPMClock presents a client view of the method setHours, and clients do
not need to know how methods do what they do. (The code that actually implements a
method is called the method body.)
The second crucial piece of the client description of setHours is the specification
Updates:
this.hours
Requires:
Ensures:
this.hours = newHours
Unit 4 - 4
describing a contract between clients of setHours and the setHours method
itself. To get you into the spirit of things, here is another example of a contract:
requires
students show up for class, stay awake, and ask questions
ensures
the instructor delivers an incredible lecture
Contracts are agreements between clients of a service and providers of the service.
Contracts have two parts: the requires clause specifies obligations that clients must meet
and the ensures clause specifies obligations providers must meet. There is a little catch,
however. Providers are obligated to meet their obligations only if clients meet their
obligations. In the second example, the obligation of the students (the client) is to come
to the class, to stay awake, and to ask questions. If students meet their obligations, the
instructor (the provider) is then obligated to deliver an incredible lecture. On the other
hand, if the students do not show up for class or fall asleep in class or sit there like bumps
on logs, the instructor can do anything she wants, since she is no longer bound to her
obligations. So, the instructor might deliver an incredible lecture, or she might tell the
story of Goldilocks and the Three Bears, or she might go to aerobics.
In the case of methods, the requires clause specifies conditions that incoming parameter
values must satisfy. Since clients provide incoming values, this is an obligation of the
client. The ensures clause specifies conditions that outgoing parameter values must
meet. This is the obligation of the method. Of course, if a client provides incoming
parameter values that do not satisfy the requires clause, then the method can supply
anything it wants for outgoing values, or it might even fail to terminate its execution!
As you might expect, the operation setHours can be used to set the hours of an am-pm
clock. Clients supply the desired new value for the hours through the formal parameter
newHours. This explains the client obligation for the incoming value of newHours:
Unit 4 - 5
Requires:
Assuming that a client supplies a good value for newHours, method setHours should
change the value of the clock so that its hours are the same as the incoming value of
newHours. But what clock variable is to be changed? There is no clock parameter in
the parameter list! Well, at least not explicitly. The operation setHours is specified in
the interface AMPMClock and is considered to be an instance method. Instance methods
must be applied to variables of a component type. This means that clients must invoke the
operation setHours with a statement like myClock.setHours(myHours) or like
yourClock.setHours(yourHours), where myClock and yourClock are
variables of a component type, described by AMPMClock, to which setHours will be
applied. (More intuitively, they are the clocks whose values are to be changed.) So,
myClock and yourClock are actually additional arguments in the call to method
setHours, but they appear just before the name of the method. In the contract for a
method, the distinguished parameter is implicit and always goes by the name this. In a
client call, the distinguished argument appears explicitly (e.g., myClock or
yourClock above). The distinguished argument is also called the receiver of the
method call.
this.hours = newHours
The assertion this.hours = newHours just says that the outgoing value of
this.hours will be the (outgoing) value of newHours. (Remember that this refers
to a variable described by AMPMClock and that values of variables described by
AMPMClock are 4-tuples.) But, you might ask, what about the outgoing values of
this.minutes, this.seconds, and this.am? Clearly setHours is not
supposed to change the minutes, seconds, and am/pm indicator of the given clock and our
Unit 4 - 6
contract would be incomplete if we did not explicitly state that they cannot change. Here
is where a convention comes into play. Any arguments that might be changed by a
method must be listed in the contract under a heading that describes how they might be
changed. Observe these lines in the contract:
Updates:
this.hours
Updates is known as a parameter mode. It simply says that the parameters listed after it
may be modified by the method and usually well look at the ensures clause to see how
they might be modified. In this case, the only argument listed is this.hours and this
indicates that setHours is only allowed to modify the value of this.hours. In other
words, the other arguments (or parts of the other arguments) must have the same
outgoing value as their incoming value: this.minutes, this.seconds, this.am,
and newHours all have the same value after the call to setHours that they had before
the call. Again, this is a convention that we will follow in all our descriptions of
components. (Later on we will see that there are a few other parameter modes, e.g.,
Replaces and Clears, describing other kinds of modifications that can occur to
parameters.)
There is one more important aspect of the contract for setHours that we should
discuss. Whenever a parameter is mentioned in the requires clause, the name clearly
refers to the incoming value of the parameter. For example, in the assertion 1 <=
newHours <= 12, we are imposing a constraint on the value provided by the client,
i.e., the incoming value of newHours. The requires clause never talks about the
outgoing value of any of the parameters. However, in the ensures clause where we
usually want to describe the outgoing values of those parameters that can be modified by
the method, sometimes we may need to refer to the incoming value of some of the
parameters as well. How can we distinguish an incoming value from an outgoing value?
We simply add a # symbol at the front of the name of the parameter to refer to the
incoming value, and assume that when no # is present, we are referring to the outgoing
value. As an example of this notation, if we had wanted to explicitly state in the ensures
Unit 4 - 7
clause of setHours that the value of this.minutes was not going to change, we
could have written it as
this.minutes = #this.minutes
simply saying that the outgoing value of this.minutes is equal to the incoming value
of the minutes of this, written as #this.minutes.
Unit 4 - 8
Client Description of setMinutes and setAM Methods
// CONTINUATION OF AMPMClock
Parameters:
Updates:
this.minutes
Requires:
Ensures:
this.minutes = newMinutes
// ------------------------------------------
Parameters:
Updates:
this.am
Ensures:
this.am = am
// AMPMClock TO BE CONTINUED...
Unit 4 - 9
4-5. Give the complete client description of setSeconds.
4-6. Suppose that myClock = (11,25,48,true) and that
newMinutes = 31. What will be the value of myClock and
Still Awake? newMinutes after the method call
myClock.setMinutes(newMinutes)? How about after the method call
myClock.setMinutes(52)?
4-7. Suppose that myClock = (11,25,48,true) and am = true. What will be
the value of myClock and am after the method call myClock.setAM(am)?
Unit 4 - 10
Client Description of hours and isAM Methods
// CONTINUATION OF AMPMClock
int hours()
hours is the name of
the method.
Reports this.hours.
// ------------------------------------------
boolean isAM()
Reports this.am.
Returns:
this.am
Ensures:
isAM = this.am
As usual, the description of these methods involves some new stuff. Well work through
the hours method; isAM is similar.
Each of the set methods such as setHours was specified as a procedure. On the
other hand, the hours method is specified as a function. The idea of a function is
Unit 4 - 11
borrowed from mathematics. Heres an example: f ( x, y ) x y y x . Clients of this little
math function supply values for the parameters x and y, and the function returns the
single value x y y x , computed from the supplied values for x and y. Notice that
returns a single value without changing the values of parameters x and y.
We can now understand the structure of the function header for hours:
Unit 4 - 12
4-8. What is the type of the return value for the function isAM?
Explain why this is the type.
Still Awake?
this.hours
Ensures:
hours = this.hours
Notice anything unusual? To start with, there is no requires clause! With a little
explanation, this is understandable. Since the parameter list is empty, the only formal
parameter for hours is the distinguished argument this, a variable with a value
described by AMPMClock. Whatever clock value a client might supply for this,
hours will be able to return the hours portion of the value (this.hours). So, there
is no need to impose any restrictions on incoming values.
There is also no Updates section, indicating that this function will not modify the value
of any of its arguments. The description of outgoing values is quite simple since this is
the only parameter and hours is not modifying any of its parameters. So we know that
this = #this.
hours = this.hours
This will always be the case for all functions. We simply let the name of the function, in
the ensures clause, stand for the single value to be returned by the function. A good way
Unit 4 - 13
to read the assertion hours = this.hours is the value to be returned by hours is
this.hours.
We should also point out that there is some redundancy in this contract. As you can see,
the Returns and Ensures entries say pretty much the same thing. This is because of how
simple this function is. For more complex functions, the Returns entry will provide a
short, informal description of the value returned by the function while the Ensures clause
usually will provide a precise mathematical description of the entire behavior of the
function.
Now is an excellent time to step back and review what's happened so far. AMPMClock
is a Java interface that provides us with a client-view description of the behavior of an
am-pm clock. In this sense, it is an abstraction of the behavior of a clock component.
Just like all interfaces it provides two things: a type (designating a set of values) and
methods that can be applied to variables whose values come from the type (i.e., from the
set of values).
Unit 4 - 14
The Emperor Has No Clothes
And now for a big surprise: It will not be sufficient for
clients to order only AMPMClock from a library!
AMPMClock provides descriptions that clients use to
understand what am-pm clocks are and can do.
AMPMClock does not provide a single piece of executable
code specifying how the methods do their job. But in a
program using AMPMClock variables, Java will need such
executable code! As a result, clients will also order, from a
library, a class component delivering the necessary
executable code. For AMPMClock, this will be a component
with a name that reads something like AMPMClock1; that is, AMPMClock1is a
component providing executable code that implements the behavior described by
AMPMClock. Think of it this way: AMPMClock describes, like an instruction manual, a
part that a client would like to use, and AMPMClock1 is the part number. In a Java
program, then, clients would declare and initialize an am-pm-clock variable as
AMPMClock myClock = new AMPMClock1();
Unit 4 - 15
Specific variable values before the
method call incoming values.
The method call.
myClock.setHours(newHours);
myClock = (7,18,57,false)
newHours = 7
Tracing tables can trace more than a single method call, as the next example shows. In
this example, isMorning is a variable of type boolean.
Unit 4 - 16
Statement Variable Values
myClock = (2,18,57,false)
newHours = 7
isMorning = true
myClock.setHours(newHours);
myClock = (7,18,57,false)
newHours = 7
isMorning = true
isMorning = myClock.isAM();
myClock = (7,18,57,false)
newHours = 7
isMorning = false
Unit Wrap-up
Comment 1: In the second tracing table notice the difference between the two statements
being traced. The statement myClock.setHours(newHours) is a call to the
procedure setHours. The effects of the procedure call are made known to the caller,
the client, through changes in the values of the client-supplied actual parameters,
myClock and newHours. (Of course, only the value of myClock is changed.) On the
other hand, the statement isMorning = myClock.isAM() is an assignment
statement, one part of which is the call to the function isAM and the other part being the
assignment of the value returned by isAM to the variable isMorning. We could have
just called the function isAM using the statement myClock.isAM() and left out the
assignment of the return value to isMorning. But this would not make much sense in
this case! isAM does not change the value of any of its parameters. So why would a
client bother to call isAM if the client does nothing with the return value? This would be
like sending someone to the ticket office to buy movie tickets, and telling them to just
leave the tickets at the ticket office! REMEMBER, usually youll want to make use of
the return value of a function call!
Unit 4 - 17
Comment 2: Comment 2 appears in the next figure. IT IS FUNDAMENTALLY
IMPORTANT. Make sure you understand it completely. Put it into an accessible, long-
term part of your memory!
Client descriptions of methods must describe all assumptions about the incoming values
of all parameters, and must describe the corresponding outgoing values of all parameters.
Such descriptions can be presented in different ways. Good descriptions will be precise
(no margin for error) and understandable (by human readers). The mechanism that is
used in CSE 2221/2231 to make such precise and understandable descriptions of methods
is contracts, where each method contract consists of two sections, a requires clause and
an ensures clause.
Unit 4 - 18
Comment 3: Comment 3 appears in the next figure. IT IS FUNDAMENTALLY
IMPORTANT. Make sure you understand it completely. Put it into an accessible, long-
term part of your memory!
High quality software components should be organized into two distinct parts. One part
describes what the component can do. We refer to this as the abstract part or interface.
The second part provides code (the how) that implements the behavior described in the
abstract part. We refer to this as the concrete part or class.
high-quality software
abstract components of two kinds:
description interface and class
of what
interface
concrete implements
description
of how
class
Unit 4 - 19
4-13. Complete the following tracing table.
Still Awake?
myClock = (8,2,43,true)
yourClock = (11,18,6,false)
transferMinutes = 7
transferMinutes = myClock.minutes();
myClock =
yourClock =
transferMinutes =
yourClock.setMinutes(transferMinutes);
myClock =
yourClock =
transferMinutes =
Unit 4 - 20