|
|
|
|
Conditions and conditional statements. |
|
Preconditions, postconditions, and class
invariants. |
|
Boolean expressions. |
|
|
|
|
postcondition: a condition the implementor
(server) guarantees will hold when a method completes execution. |
|
invariant: a condition that always holds true. |
|
class invariant: an invariant regarding
properties of class instances: that is, a condition that will always be
true for all instances of a class. |
|
|
|
|
class invariant: component variable tally will
always be greater than or equal to zero. |
|
This holds true with the methods currently
defined. |
|
postcondition: the method count must make sure
that tally is greater or equal to zero when the method completes execution. |
|
|
|
|
Adding a method decrementCount threatens the
class invariant constraint that tally be greater than or equal to zero. |
|
|
|
public void decrementCount () { |
|
tally = tally - 1; |
|
} |
|
We must guard the assignment statement with a
condition statement. |
|
|
|
|
Postconditions and class invariants are part of
class specification but not the implementation. Therefore they should be included in comments but not in the
implementation. |
|
/** |
|
*
Current count;the number of items |
|
*
counted. |
|
*
ensure: |
|
* count >= 0 |
|
*/ |
|
public
int count () { … } |
|
|
|
|
private int tally; //current count |
|
//invariant: |
|
// tally >= 0 |
|
|
|
|
Syntax: if (condition) statement |
|
|
|
|
|
|
|
|
|
|
|
|
|
A composite statement. |
|
|
|
|
|
|
/** |
|
*Decrement positive count by 1 |
|
*/ |
|
|
|
public void decrementCount () { |
|
if (tally > 0) |
|
tally = tally - 1; |
|
} |
|
|
|
|
|
|
/** |
|
* Damage
(hit points) required to defeat |
|
* this
Explorer. |
|
* ensure: |
|
* stamina >= 0 |
|
*/ |
|
public int stamina () { |
|
return staminaPoints; |
|
} |
|
… |
|
private int staminaPoints;//current stamina |
|
//invariant:
//staminaPoints >= 0 |
|
|
|
|
If stamina reaches 0, an explorer is defeated. |
|
One possible solution: |
|
public void takeHit (int hitStrength){ |
|
if (hitStrength <= staminaPoints) |
|
staminaPoints = staminaPoints -
hitStrength; |
|
} |
|
But this rarely lets the staminaPoints reach zero. |
|
|
|
|
public void takeHit (int hitStrength){ |
|
if (hitStrength <= staminPoint) |
|
staminaPoints = staminaPoints -
hitStrength; |
|
if (hitstrength > staminaPoints) |
|
staminaPoints = 0; |
|
} |
|
What is wrong with this approach? |
|
|
|
|
It may meet the first condition and then in its
changed state, meet the second condition as well. |
|
|
|
|
Syntax: if (condition) statement1 else statement2 |
|
|
|
|
public Explorer(… , int stamina, …) { … |
|
if (stamina >=0) |
|
staminaPoints = stamina; |
|
else |
|
staminaPoints = 0; … |
|
} |
|
public void takeHit (int hitStrength){ |
|
if (hitStrength <= staminaPoints) |
|
staminaPoints = staminaPoints -
hitStrength; |
|
else |
|
staminaPoints = 0; |
|
} |
|
|
|
|
What should we do if the constructor is called
with a negative value for the parameter stamina? |
|
|
|
public Explorer (String name,
rooms.Room location, int hitStrength, |
|
int stamina) { … |
|
if (stamina >= 0) |
|
staminaPoints = stamina; |
|
else |
|
staminaPoints = 0; … |
|
} |
|
|
|
|
|
|
Syntax: { statement1 statement2
… } |
|
In this statement, |
|
|
|
if (hitStrength <= staminaPoints) |
|
staminaPoints = staminaPoints -
hitStrength; |
|
else |
|
staminaPoints = 0; |
|
strengthPoints = 0; |
|
|
|
The last statement is not part of the else
condition. |
|
|
|
|
|
Braces are used to create a block or compound
statement, which is a single composite statement. |
|
if (condition) { if (condition) { |
|
statement1 statement1 |
|
… … |
|
statementn statementn |
|
} } else { |
|
statement1 |
|
… |
|
statementn |
|
} |
|
|
|
|
if (hitStrength <= staminaPoints) |
|
staminaPoints = staminaPoints -
hitStrength; |
|
else { |
|
staminaPoints = 0; |
|
strengthPoints = 0; |
|
} |
|
|
|
|
|
Relational operators: |
|
< less than |
|
<= less than or equal |
|
> greater than |
|
>= greater than or equal |
|
== equal (A single ‘=‘ denotes assignment.) |
|
!= not equal |
|
A relational expression consists of two
expressions joined with a relational operator. |
|
|
|
|
Let i1=10, i2=-20, i3=30. |
|
i1 < 12 -> true |
|
i1 <= 10 -> true |
|
i3 == i1 -> false |
|
i1 != 2 -> true |
|
i1 < 10 -> false |
|
i2 > 0 -> false |
|
2*i1 == i2+40 -> true |
|
i2*(-1) != i1+i1 -> false |
|
|
|
|
An expression like a<b<c is illegal. |
|
If one operand is an int and the other is a double,
the int is first converted to a double. 10 > 2.5 º
10.0 > 2.5 |
|
Since floating point values are approximations
for real numbers, we should avoid using equality or inequality operators
with them. |
|
(1.0/6.0+1.0/6.0+1.0/6.0+ |
|
1.0/6.0+1.0/6.0+1.0/6.0) == 1.0 º false |
|
|
|
|
Booleans
can be stored as variables. |
|
|
|
private boolean tooBig; |
|
tooBig = true; |
|
tooBig = i1 > 10; |
|
|
|
|
! not |
|
&& and |
|
|| or |
|
! booleanExpression |
|
booleanExpression && booleanExpression |
|
booleanExpression || booleanExpression |
|
|
|
A boolean expression evaluates to either true or
false. |
|
|
|
|
|
|
“Not” reverses boolean values. i.e. !true º false !false º true |
|
i1=10 |
|
!( i1 > 9) º !(true)
º false |
|
“Not” has high precedence. |
|
! i1 > 9 º (!i1) > 9 º
illegal |
|
Generally avoid the “not” operator. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(i1>10)||(i1==10)ºfalse||trueºtrue |
|
(i1>10)||(i1<0)ºfalse||falseºfalse |
|
(i1>0)&&(i1<5)ºtrue&&falseºfalse |
|
(i1>0)&&(i1<20)ºtrue&&trueºtrue |
|
|
|
|
The && and || have lower precedence than
the relational operators, but parentheses are still useful because they
enhance readability. |
|
The && and || are lazy operators that
evaluate only the left operand only when that suffices. |
|
|
|
|
Consider: |
|
(5 == 4) && ???? |
|
(5 != 4) || ???? |
|
Does it matter what the second operands are? |
|
This can protect against runtime errors such as
an attempt to divide by zero. |
|
Example: (x == 0) || (y/x < 10) |
|
(x != 0) &&
(y/x < 10) |
|
|
|
|
Useful for simplifying expressions. |
|
|
|
!(b1 && b2) º !b1 || !b2 |
|
!(b1 || b2) º !b1 && !b2 |
|
|
|
!(i1>5 && i1<8) º !(i1>5) ||
!(i1<8) |
|
|
|
|
|
Consider a method that determines if a year is a
leap year. |
|
The Gregorian calendar stipulates that a year is
a leap year if it is divisible by 4, unless it is also divisible by 100, in
which case it is a leap year if and only if it is divisible by 400. For
example, 1900 is not a leap year, but 2000 is. |
|
|
|
(year % 100 != 0 && year % 4 == 0) || |
|
(year % 100 == 0 && year % 400 == 0) |
|
|
|
|
Another way of representing these rules uses
cases and nested conditional statements. |
|
public boolean isLeapYear (int year) { |
|
boolean aLeapYear; |
|
if (year % 4 == 0) |
|
if (year % 100 == 0) |
|
aLeapYear = (year % 400 == 0); |
|
else |
|
aLeapYear = true; |
|
else |
|
aLeapYear = false; |
|
return aLeapYear; |
|
} |
|
|
|
|
|
|
The traffic signal class cycles through 4
states: |
|
LEFT (left turn arrow) |
|
GO
(green light) |
|
CAUTION (yellow light) |
|
STOP
(red light) |
|
The component variable currentState will hold
one of these states. |
|
|
|
|
advance moves currentState to the next state. |
|
public void advance () { |
|
private int currentState; |
|
if (currentState == LEFT) |
|
currentState = GO; |
|
else if (currentState == GO) |
|
currentState = CAUTION; |
|
else if (currentState == CAUTION) |
|
currentState = STOP; |
|
else //currentState == STOP |
|
currentState = LEFT; |
|
} |
|
|
|
|
|
Which if statement is this else statement
associated with? |
|
|
|
if (condition1) |
|
if (condition2) |
|
statement1 |
|
else |
|
statement2 |
|
|
|
|
|
|
It is associated with the second if (B). |
|
To associate it with the first, add braces
around everything contained between the first if and the else. |
|
|
|
if (condition1) { |
|
if (condition2) |
|
statement1 |
|
} else |
|
statement2 |
|
|
|
|
|
|
Responsibilities: |
|
Know: |
|
The combination |
|
whether unlocked or locked |
|
Do: |
|
lock |
|
unlock |
|
|
|
|
|
Class: CombinationLock |
|
Queries: |
|
is open |
|
Commands: |
|
lock |
|
unlock |
|
|
|
|
public class CombinationLock |
|
Contructor: |
|
public CombinationLock (int
combination) |
|
|
|
Queries: |
|
public boolean isOpen() |
|
|
|
Commands: |
|
public void close () |
|
public void open(int combination) |
|
|
|
|
|
|
Component variables: |
|
private int combination; |
|
private boolean isOpen; |
|
|
|
|
The straightforward implementations: |
|
|
|
public boolean isOpen () { |
|
return isOpen; |
|
} |
|
|
|
public void close () { |
|
isOpen = false; |
|
} |
|
|
|
|
When the constructor is being executed, there
are two distinct variables with the same name. (Component variable and
local variable combination). |
|
The keyword this refers to the “current object.”
Therefore this.combination refers to the component variable. |
|
If the variable does not include the object
reference this in front of it, it is a reference to the local variable. |
|
|
|
|
|
|
public CombinationLock (int combination) { |
|
this.combination = combination; |
|
isOpen = false; |
|
} |
|
We could write the second assignment as |
|
this.isOpen = false; |
|
But there is no ambiguity, so it is not needed. |
|
|
|
|
|
|
A final method: |
|
|
|
public void open (int combination) { |
|
if (this.combination == combination) |
|
isOpen = true; |
|
} |
|
|
|
|
|
|
This lock has a 3 digit combination. |
|
To open the lock, the client provides the digits
one at a time. |
|
If the client enters the three digits of the
combination in order, the lock opens. |
|
It doesn’t matter how many digits the client
provides, as long as the combination is given. |
|
|
|
|
Digit Entered |
|
4 |
|
1 |
|
2 |
|
4 |
|
3 |
|
1 |
|
2 |
|
3 |
|
|
|
Digit Entered |
|
1 |
|
2 |
|
3 |
|
4 |
|
7 |
|
|
|
|
public class CombinationLock |
|
Constructor: |
|
public CombinationLock (int combination) |
|
require: combination >= 0 &&
combination <=999 |
|
Queries: |
|
public boolean isOpen () |
|
Commands: |
|
public void close () |
|
public void enter (int digit) |
|
require:
digit >=0 && digit <=9 |
|
|
|
|
|
|
A condition the client of a method must make
sure holds when the method is invoked. |
|
The constructor and method enter have certain
requirements that must be met for them to execute properly. These are the “require:”s found it the
definition on the previous slide. |
|
Somewhat like the “unleaded gas only” sign near
the gas cap on an automobile. |
|
|
|
|
|
Know: |
|
the 3-digit combination. |
|
whether locked or unlocked. |
|
the last three digits entered. |
|
Do: |
|
lock. |
|
unlock, when given the proper combination. |
|
accept a digit. |
|
|
|
|
Using the % and / operator, we can extract each
digit. |
|
Suppose a combination 123. |
|
123 % 10 -> 3 |
|
123 / 10 -> 12 |
|
12 % 10 -> 2 |
|
12 / 10 -> 1 |
|
% 10 gets the last digit and / 10 get the
remaining digits. |
|
|
|
|
// entered1, entered2, entered3 are the last
three |
|
// digits entered, with entered3 the most
recent. |
|
// a value of -1 indicates the digit has not
been |
|
// entered. |
|
private int entered1; |
|
private int entered2; |
|
private int entered3; |
|
// invariant: |
|
// entered1 >= -1 && entered1 <= 9 && |
|
// entered2 >= -1 && entered2 <= 9 && |
|
// entered3 >= -1 && entered3 <= 9 |
|
|
|
|
|
|
|
|
|
|
Boolean expressions. |
|
Conditional statements. |
|
if (condition) |
|
statement |
|
if (condition) |
|
statement1 |
|
else |
|
statement2 |
|
Compound statements {statement1
statement2 … statementn}. |
|
Preconditions, postconditions, invariants. |
|
|
|
|
|