810 likes | 821 Views
Chapter 4 : Conditionals. Objectives. After studying this chapter you should understand the following: the notions of preconditions, postconditions, and invariants; the purpose of a conditional statement; the function of boolean expressions; the purpose of a compound statement.
E N D
Objectives • After studying this chapter you should understand the following: • the notions of preconditions, postconditions, and invariants; • the purpose of a conditional statement; • the function of boolean expressions; • the purpose of a compound statement. • Also, you should be able to: • write and evaluate boolean expressions; • write conditional statements of various forms; • implementation methods that use conditional statements; • implement a class tester which automatically verifies test results. NH-Chapter4
Postconditions and invariants • Method currentCount in Counter is specified as • Specification stipulates invoking method returns a value of type int. /** * The number of items counted. */ public int currentCount () { … NH-Chapter4
Postconditions and invariants • Can be more precise in specifying result : integer result is non- negative. • Postcondition: condition that implementor promises will be satisfied when method completes execution. • Implementor must make sure that the method satisfies the postcondition. /** * The number of items counted. * * @ensure this.currentCount() >= 0 */ public int currentCount () { … NH-Chapter4
Postconditions and invariants • Need to make sure instance variable used to store current count will never contain a negative value. • Document this via a class invariant: private int count; // current count // invariant: count >= 0 • A class invariant will always be true of all instances of the class. NH-Chapter4
Postconditions and invariants • If we add decrementCount to Counter: public void decrementCount () Decrement positive count by 1; zero count remains zero. • In implementation, need to add guard to be sure not to decrement when count == 0 NH-Chapter4
The if-then statement if (condition) statement B E G I N true condition false statement E N D NH-Chapter4
Implemeting decrementCount /** * Decrement positive count by 1; * zero count remains zero */ public void decrementCount () { if (count > 0) count = count - 1; } NH-Chapter4
Explorer: invariants and guards • Restrict Explorer’s tolerance to be a non-negative integer. • Need to insure value assigned in each case is not negative. private int tolerance; // current tolerance // invariant: tolerance >= 0 /** * Damage (hit points) required to defeat * this Explorer. * * @ensure tolerance >= 0 */ public int tolerance () { return tolerance; } NH-Chapter4
Explorer: invariants and guards • Consider method takeThat. • Need to guard the two statements: if (hitStrength <= tolerance) tolerance = tolerance - hitStrength; if (hitStrength > tolerance) tolerance = 0; • But, only one of those should execute when invokingtakeThat. NH-Chapter4
if-then-else statement if (condition) statement1 else statement2 B E G I N false true condition statement statement 2 1 E N D NH-Chapter4
Implementing method takeThat public void takeThat (int hitStrength) { if (hitStrength <= tolerance) tolerance = tolerance - hitStrength; else tolerance = 0; } NH-Chapter4
Implementing constructor public Explorer (String name, Room location,int strength, int tolerance) { … if (tolerance >= 0) this.tolerance = tolerance; else this.tolerance = 0; … } NH-Chapter4
if (condition) { statement1 … statementN } if (condition) { statement11 … statement1N }else { statement21 … statement2M } Compound statements NH-Chapter4
Conditions: boolean expressions • Boolean expressions: • Produce boolean values when evaluated; • Evaluate to true or false. • Can declare boolean variables, and assign values: tooBig = true; Or tooBig = size > 10; private boolean tooBig; • And can assign values to it: NH-Chapter4
Handling multiple cases • A conditional statement divides problem into two cases to be considered independently. • In many problems, there are more than two cases, or cases need to be further divided into subcases. • Use nesting conditional statements. NH-Chapter4
Handling multiple cases • Assume class Date with properties day, month,year. • Implement a Date’s query that will tell whether or not a date occurs in a leap year. public boolean isLeapYear () This Date occurs in a leap year. NH-Chapter4
Case: year not divisible by 4 not a leap year. Case: year divisible by 4 ??? Case: divisible by 100 ??? Case: not divisible by 100is leap Case: divisible by 400is leap Case: not divisible by 400is not leap Handling multiple cases isLeapYear NH-Chapter4
Handling multiple cases // This Date occurs in a leap year. public boolean isLeapYear () { boolean aLeapYear; if (year % 4 == 0) if (year % 100 == 0) // if divisible by 100, // must also be divisible by 400 aLeapYear = (year % 400 == 0); else // divisible by 4, not by 100 aLeapYear = true; else // not divisible by 4 aLeapYear = false; return aLeapYear; } NH-Chapter4
Cascading conditionals • When problem splits into more than two cases: • “cascade” if-then-else statements. if (case1) handleCase1 else if (case2) handleCase2 … else if (penultimateCase) handlePenultimateCase else handleLastCase NH-Chapter4
change : case: light is GREEN case: light is YELLOW case: light is RED change to GREEN change to YELLOW change to RED TrafficLight’s change() method NH-Chapter4
TrafficLight’s change() method public void change () { if (light == GREEN) light = YELLOW; else if (light == YELLOW) light = RED; else // light == RED light = GREEN; } NH-Chapter4
Dangling else • There is an ambiguity as to whether the structure • Is it an if-then nested in an if-then-else, or an if-then-else nested in an if-then? if (condition1) if (condition2) statement1 else statement2 NH-Chapter4
Dangling else NH-Chapter4
if (condition1) if (condition2) statement1 else statement2 if (condition1) { if (condition2) statement1 else statement2 } Dangling else: equivalent statements NH-Chapter4
Example: combination lock • Responsibilities: • Know: • The combination • whether unlocked or locked • Do: • lock • unlock NH-Chapter4
CombinationLock class • Class: CombinationLock • Queries: • is open • Commands: • lock • unlock NH-Chapter4
Class CombinationLock specifications publicclass CombinationLock Contructor: public CombinationLock (int combination) Queries: public boolean isOpen() Commands: public void close () public void open(int combination) NH-Chapter4
Class CombinationLock implementation Component variables: private int combination; private boolean isOpen; NH-Chapter4
Structure for a simple test public class CombinationLock { private int combination; private boolean isOpen; public CombinationLock (int combination) { } public boolean isOpen () { return true; } public void close () { } public void open (int combinationToTry) { } } NH-Chapter4
Structure for a simple test class CombinationLockTest { private CombinationLock lock; public CombinationLockTest () { } publicvoid runTest () { } } public class TestCombinationLock { public static void main (String[] argv) { (new CombinationLockTest()).runTest(); } } NH-Chapter4
Precondition • A condition client of a method must make sure holds when method is invoked. • “Require”s : Constructor and method enterhave requirements that clients must meet for them to execute properly. NH-Chapter4
Constructor specifications /** * Create a lock with the specified combination. * * @require: * 0 <= combination && combination <= 999 * @ensure: * this.isOpen() */ public CombinationLock (int combination) … NH-Chapter4
Testing locks • Need method to create and test lock with given combination: • Invoke this method in runTest for each lock to test. private void testLock (int combination) Test a lock with the specified combination. public void runTest () { testLock(0); testLock(123); testLock(999); } NH-Chapter4
Automating checking of test results private void verify (boolean test, String message) { if (!test) System.out.println( "Verification failed: " + message); } NH-Chapter4
testLock method • testLock method must create lock and run initial state test: private void testLock (int combination) { lock = new CombinationLock(combination); testInitialState(); } NH-Chapter4
testLock method • Initial state test should make sure that lock is open. • So, instead of writing the test method: • Write: private void testInitialState() { System.out.println("Initial state: " + lock.isOpen()); } private void testInitialState() { verify(lock.isOpen(), "initial state"); } NH-Chapter4
Class CombinationLock implementation • The straightforward implementations: public CombinationLock (int combination) { this.combination = combination; this.isOpen = true; } public boolean isOpen () { return isOpen; } NH-Chapter4
Class CombinationLock implementation • In constructor, there are two variables with same name. • Component variable and • local variable combination. • this.combination refers to component variable. • If variable does not include object reference this in front of it, it is a reference to local variable. NH-Chapter4
Class CombinationLock implementation NH-Chapter4
Method to test close • write method to test close, and invoke it from testLock: private void testClose() { lock.close(); verify(!lock.isOpen(), "close open lock"); lock.close(); verify(!lock.isOpen(), "close closed lock"); } private void testLock (int combination) { lock = new CombinationLock(combination); testInitialState(); testClose(); } NH-Chapter4
Implementing close in Lock • Command close is also easy to implement: public void close () { isOpen = false; } NH-Chapter4
Method to test open • Test for the method open: four cases to test: • closed lock, correct combination: lock opens; • open lock, correct combination: lock remains open; • closed lock, incorrect combination: lock remains closed. • open lock, incorrect combination: lock remains open; • Test depends on combination, so pass correct combination as argument: privatevoidtestOpen (int combination) NH-Chapter4
testOpen method private void testOpen (int combination) { int badCombination = (combination + 1) % 1000; // test with correct combination: lock.close(); lock.open(combination); // open closed lock verify(lock.isOpen(), "open closed lock"); lock.open(combination); // open opened lock verify(lock.isOpen(), "open opened lock"); // test with incorrect combination: lock.open(badCombination); // try opened lock verify(lock.isOpen(), "bad comb, opened lock"); lock.close(); lock.open(badCombination); // try closed lock verify(!lock.isOpen(), "bad comb, closed lock"); } NH-Chapter4
testOpen method • Add an invocation of this method to testLock: private void testLock (int combination) { lock = new CombinationLock(combination); testInitialState(); testClose(); testOpen(combination); } NH-Chapter4
Method open implementation • The following implementation of open fails the tests. • test will produce the following output: • Verification failed: bad comb, opened lock • Verification failed: bad comb, opened lock • Verification failed: bad comb, opened lock • Root of problem: attempt to open an already opened lock with incorrect combination should not close it. public void open (int combination) { isOpen = (this.combination == combination) } NH-Chapter4
Method open implementation • Correct implementation of method uses a conditional statement that opens the lock if the combination is correct, and does nothing if the combination is not correct: public void open (int combinationToTry) { if (this.combination == combinationToTry) isOpen = true; } NH-Chapter4
Digit by digit lock • This lock has a 3 digit combination. • To open the lock, client provides the digits one at a time. • If client enters three digits of combination in order, lock opens. • It doesn’t matter how many digits client provides, as long as combination is given. NH-Chapter4
Digit by digit lock: combination 123 Digit Entered 4 1 2 4 3 1 2 3 Digit Entered 1 2 3 4 7 Lock Status closed closed closed closed closed closed closed open Lock Status closed closed open open open NH-Chapter4
Digit by digit lock: combination 123 • if client gives command close when combination has been partly entered, Client Command Lock Status enter 1 closed enter 2 closed close closed enter 3 ? Client Command Lock Status open enter 1 open enter 2 open close closed enter 3 ? • command close resets lock, entire combination must be entered. NH-Chapter4