Chapter 8 – Designing Classes

Copyright © 2014 by John Wiley & Sons. All rights reserved.

1

Chapter Goals

 To learn how to choose appropriate classes for a given problem

 To understand the concept of cohesion

 To minimize dependencies and side effects

 To learn how to find a data representation for a class

 To understand static methods and variables

 To learn about packages

Copyright © 2014 by John Wiley & Sons. All rights reserved.

2

Discovering Classes

 A class represents a single concept from the problem domain.

 Name for a class should be a noun that describes concept .

• Concepts from mathematics:

Point

Rectangle

Ellipse

• Concepts from real life:

BankAccount

CashRegister

Copyright © 2014 by John Wiley & Sons. All rights reserved.

3

Discovering Classes

 Actors

• objects do some kinds of work for you:

Scanner

Random // Better name: RandomNumberGenerator

 Utility classes

• no objects, only static methods and constants:

Math

 Program starters :

• a class with only a main method

Copyright © 2014 by John Wiley & Sons. All rights reserved.

4

Naming Classes

 The class name should indicate what objects of the class will do :

• Paycheck is a better name than PaycheckProgram .

 Don't turn a single operation action into a class:

• Paycheck is a better name than ComputePaycheck .

Copyright © 2014 by John Wiley & Sons. All rights reserved.

5

Question

What is the rule of thumb for finding classes?

Answer: Look for nouns in the problem description.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

6

Designing Good Methods - Cohesion

 A class should represent a single concept .

 The public interface of a class is cohesive if all of its features are related to the concept that the class represents.

 The members of a cohesive team have a common goal .

Copyright © 2014 by John Wiley & Sons. All rights reserved.

7

Designing Good Methods - Cohesion

 This class lacks cohesion.

public class CashRegister

{ public static final double QUARTER_VALUE = 0.25; public static final double DIME_VALUE = 0.1; public static final double NICKEL_VALUE = 0.05;

. . .

public void receivePayment(int dollars, int quarters, int dimes, int nickels, int pennies)

. . .

}

 It contains two concepts:

• A cash register that holds coins and computes their total

• The values of individual coins.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

8

Designing Good Methods - Cohesion

 Solution: Make two classes: public class Coin

{ double value;

String type; public Coin(double aValue, String aName) { . . . } public double getValue() { . . . }

. . .

} public class CashRegister

{

. . . public void receivePayment(int coinCount, Coin coinType)

{ payment = payment + coinCount * coinType.getValue();

}

. . .

}

 Now CashRegister class can handle any type of coin .

Copyright © 2014 by John Wiley & Sons. All rights reserved.

9

Minimizing Dependencies

 A class depends on another class if its methods use that class in any way.

• CashRegister depends on Coin

 UML: Unified Modeling Language

• Notation for object-oriented analysis and design

Copyright © 2014 by John Wiley & Sons. All rights reserved.

10

Minimizing Dependencies

Figure 1 UML class diagram showing dependency relationship between the CashRegister and Coin

Classes.

 The Coin class does not depend on the CashRegister class.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

11

Separating Accessors and Mutators

 A mutator method:

• changes the state of an object (i.e. modify value of instance variables) .

• E.g. withdraw method in BankAccount class

 An accessor method:

• asks an object to compute a result

• doesn’t change the state (i.e. only looks up value of instance variable) .

• E.g. getBalance method in BankAccount class

 An immutable class :

• Class with no mutator methods .

• E.g. String is an immutable class

• No method in the String class can modify the contents of a string.

• References to objects of an immutable class can be safely shared.

 A mutable class :

• accessors + mutators

Copyright © 2014 by John Wiley & Sons. All rights reserved.

12

Separating Accessors and Mutators

 Mutator method :

• Change the state of an object

• Usually a method that does NOT return a value.

• In general, SHOULD have return type void

• Sometimes, can return an informational value.

• E.g. ArrayList remove method returns true if the removal was successful.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

13

Minimizing Side Effects

 In general, a method should not modify its parameter variables .

/** Computes the total balance of the given accounts.

@param accounts a list of bank accounts

*/ public double getTotalBalance(ArrayList<BankAccount> accounts )

{ double sum = 0; while (accounts.size() > 0)

{

BankAccount account = accounts.remove(0) ; // Not recommended sum = sum + account.getBalance();

} return sum;

}

 Such a side effect would not be what most programmers expect.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

14

Programming Question

 Add following method below main moethod of BankAccountTester class.

}

{ public double getTotalBalance(ArrayList<BankAccount> accounts) double sum = 0; while (accounts.size() > 0)

{

BankAccount account = accounts.remove(0); // Not recommended sum = sum + account.getBalance();

} return sum;

 Modify main method by creating array list accounts and adding 3 bank account objects with balance $1000, $2000 and $3000 respectively.

Print the balances of each account object balance.

 Next call getTotalBalance method with accounts as argument

 Print balances of each account object in acconts arrayList again.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

15

Answer

BankAccountTester.java

import java .

util .

ArrayList ; public class BankAccountTester

{ public static void main ( String args [])

{

ArrayList < BankAccount > accounts = new ArrayList < BankAccount >();

BankAccount acct1 = new BankAccount ( 1000.00

); accounts .

add ( acct1 );

BankAccount acct2 = new BankAccount ( 2000.00

); accounts .

add ( acct2 );

BankAccount acct3 = new BankAccount ( 3000.00

); accounts .

add ( acct3 ); for ( BankAccount acct : accounts )

System .

out .

print ( "BankAccount balance before:" + acct .

getBalance ());

System .

out .

println (); getTotalBalance ( accounts );

} for ( BankAccount acct : accounts )

System .

out .

print ( "BankAccount balance after:" + acct .

getBalance ());

System .

out .

println (); public static double getTotalBalance ( ArrayList < BankAccount > accounts )

{ double sum = 0 ; while ( accounts .

size () > 0 )

{

}

BankAccount account = accounts .

remove ( 0 ); // Not recommended sum = sum + account .

getBalance ();

} return sum ;

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

16

 Output:

Copyright © 2014 by John Wiley & Sons. All rights reserved.

17

Minimizing Side Effects

 The following method mutates the System.out

object , which is not a part of the BankAccount object.

public void printBalance() // Not recommended

{

System.out.println("The balance is now $" + balance);

}

 That is a side effect.

 Lesson learned:

• When designing methods, minimize side effects.

• Keep most of your classes free from input and output operations

Copyright © 2014 by John Wiley & Sons. All rights reserved.

18

Question

Is the Rectangle class immutable?

Copyright © 2014 by John Wiley & Sons. All rights reserved.

19

Answer

Is the Rectangle class immutable?

Answer: No – translate is a mutator.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

20

static Variables and Methods - Variables

 A static variable:

• Also called class variables

• Belongs to the class , not to any object of the class.

• E.g. To assign bank account numbers sequentially

• Have a single value of lastAssignedNumber that is a property of the class, not any object of the class.

• Declare it using the static reserved word public class BankAccount

{ private double balance; private int accountNumber; private static int lastAssignedNumber = 0; public BankAccount(double balance)

{ this.balance = balance; lastAssignedNumber++; accountNumber = lastAssignedNumber;

}

. . .

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

21

Programming Question

 Modify BankAccount class to incorporate an accountNumber variable (and lastAssignedNumber ).

Implement a toString method that returns a string with the String representation of class(E.g. “Bank Account

No:1 balance:1000.0”).

 Modify BankAccountTester class to create multiple bank accounts with different balances and print the details of each bank account using toString method.

 A sample run is shown:

Copyright © 2014 by John Wiley & Sons. All rights reserved.

22

Answer

BankAccount.java

public class BankAccount

{ private double balance ; private int accountNumber ; private static int lastAssignedNumber = 0 ; public BankAccount ( double balance )

{ this .

balance = balance ; lastAssignedNumber ++; accountNumber = lastAssignedNumber ;

} public String toString ()

{ return "Bank Account No:" + accountNumber + " balance:" + balance ;

}

}

BankAccountTester.java

public class BankAccountTester

{ public static void main ( String args [])

{

BankAccount acct1 = new

BankAccount ( 1000.00

);

BankAccount acct2 = new

BankAccount ( 2000.00

);

BankAccount acct3 = new

BankAccount ( 3000.00

);

System .

out .

println ( acct1 );

System .

out .

println ( acct2 );

System .

out .

println ( acct3 );

}

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

23

static Variables and Methods

 Every BankAccount object has its own balance and accountNumber instance variables

 All objects share a single copy of the lastAssignedNumber variable (static/class variable)

• That variable is stored in a separate location, outside any

BankAccount objects

Copyright © 2014 by John Wiley & Sons. All rights reserved.

24

static Variables and Methods

Figure 5 A static Variable and Instance Variables

25

static Variables and Methods

 static variables:

• S hould always be declared as private ,

• This ensures that methods of other classes do not change their values

 static constants:

• M ay be either private or public public class BankAccount

{ public static final double OVERDRAFT_FEE = 29.95;

. . .

}

• Methods from any class can refer to the constant as

BankAccount.OVERDRAFT_FEE

Copyright © 2014 by John Wiley & Sons. All rights reserved.

26

static Variables and Methods - Methods

 Sometimes a class defines methods that are not invoked on an object

• Called a static method

 Example: sqrt method of Math class

• a static method

• invoked as Math.sqrt(x)

• No object of the Math class is constructed.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

27

static Variables and Methods

 You can define your own static methods: public class Financial

{

/** Computes a percentage of an amount.

@param percentage the percentage to apply

@param amount the amount to which the percentage is applied

@return the requested percentage of the amount

*/ public static double percentOf(double percentage, double amount)

{ return (percentage / 100) * amount;

}

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

28

static Variables and Methods

 When calling such a method , supply the name of the class containing it: double tax = Financial.percentOf(taxRate, total);

 The main method is always static .

• When the program starts, there aren’t any objects.

• Therefore, the f irst method of a program MUST be a static method.

 Programming Tip:

• Minimize the Use of static Methods

Copyright © 2014 by John Wiley & Sons. All rights reserved.

29

Question

Name two static variables of the System class.

Answer: System.in

and System.out

.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

30

Question

Name a static constant of the Math class.

Answer: Math.PI

Copyright © 2014 by John Wiley & Sons. All rights reserved.

31

Question

The following method computes the average of an array of numbers: public static double average(double[] values)

Why should it not be defined as an instance method?

Answer: The method needs no data of any object. The only required input is the values argument.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

32

Question

Harry tells you that he has found a great way to avoid those pesky objects: Put all code into a single class and declare all methods and variables static . Then main can call the other static methods, and all of them can access the static variables. Will Harry's plan work? Is it a good idea?

Answer: Yes, it works. static methods can access static variables of the same class. But it is a terrible idea. As your programming tasks get more complex, you will want to use objects and classes to organize your programs.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

33

Packages

 Package: Set of related classes

 Important packages in the Java library:

/opt/java-jdk/src.zip

Copyright © 2014 by John Wiley & Sons. All rights reserved.

34

Organizing Related Classes into Packages

In Java, related classes are grouped into packages.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

35

Organizing Related Classes into Packages

 To put classes in a package, you must place a line package packageName ; as the first instruction in the source file containing the classes.

 Package name

• consists of one or more identifiers separated by periods .

• Usually all lower case

Copyright © 2014 by John Wiley & Sons. All rights reserved.

36

 To put the Financial class into a package named com.horstmann.bigjava

, the Financial.java

file must start as follows: package com.horstmann.bigjava; public class Financial

{

. . .

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

37

Organizing Related Classes into Packages

 A special package: default package

• Has no name

• No package statement

• If you did not include any package statement at the top of your source file o its classes are placed in the default package.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

38

Package Names

 Use packages to avoid name clashes : java.util.Timer

vs.

javax.swing.Timer

 Package names should be unique .

 A good choice for package name:

• turn the domain name in reverse: com.horstmann.bigjava

• Or write your email address backwards: edu.sjsu.cs.walters

Copyright © 2014 by John Wiley & Sons. All rights reserved.

39

Syntax 8.1 Package Specification

Copyright © 2014 by John Wiley & Sons. All rights reserved.

40

Packages and Source Files

 The path of a class file must match its package name .

 The parts of the name between periods represent successively nested directories.

 Base directory:

• holds your program's files

• Place the subdirectory inside the base directory.

• If your homework assignment is in a directory

/home/britney/hw8/problem1

Place the class files for the com.horstmann.bigjava

package into the directory: o /home/britney/hw8/problem1/com/horstmann/bigjava (UNIX) o Or c:\Users\Britney\hw8\problem1\com\horstmann\bigjava (Windows)

41

Packages and Source Files

Figure 6 Base Directories and Subdirectories for Packages

Copyright © 2014 by John Wiley & Sons. All rights reserved.

42

Programming Question

 Create a package cs160:

1. Modify both BankAccount.java and CashRegister.java to include the package statement: package cs160;

2. Copy their main method bodies in corresponding Tester classes as the last method in classes.

Download classes from class website.

3. Compile these two files and copy the two .class files generated into a subdirectory called cs160.

cs160

BankAccount.java

BankAccount.class

CashRegister.java

CashRegister.class

Copyright © 2014 by John Wiley & Sons. All rights reserved.

You will find that for successful compilation you need to manually create cs160 folder and put source

(java) files there.

Once compiled, source files are not required

43

 Test if it works:

• From current directory (shell prompt)

$ java cs160.BankAccount

$ java cs160.CashRegister

Copyright © 2014 by John Wiley & Sons. All rights reserved.

44

 Alternative way to create packages (easier and recommended):

1. Create/modify your java files in any location you want.

E.g. BankAccount.java

2. Go to shell prompt/command line and navigate (cd) to folder with source files

Copyright © 2014 by John Wiley & Sons. All rights reserved.

45

3. Type javac command to compile each source file

E.g

javac -d . BankAccount.java

This will automatically create the directory structure and place

.class file in ch8 directory.

some directory

BankAccount.java

cs160 ch8

BankAccount.class

Copyright © 2014 by John Wiley & Sons. All rights reserved.

46

Answer package cs160 ; import java .

util .

ArrayList ; public class BankAccount { private double balance ; private int accountNumber ; private static int lastAssignedNumber = 0 ; public BankAccount ( double balance ) { this .

balance = balance ; lastAssignedNumber ++; accountNumber = lastAssignedNumber ;

} private double getBalance () { return balance ;

} public String toString () { return "Bank Account No:" + accountNumber + " balance:" + balance ;

} public static void main ( String args []) {

ArrayList < BankAccount > accounts = new ArrayList < BankAccount >();

BankAccount acct1 = new BankAccount ( 1000.00

); accounts .

add ( acct1 );

BankAccount acct2 = new BankAccount ( 2000.00

); accounts .

add ( acct2 );

BankAccount acct3 = new BankAccount ( 3000.00

); accounts .

add ( acct3 );

} for ( BankAccount acct : accounts )

System .

out .

print ( "BankAccount balance before:" + acct .

getBalance ());

System .

out .

println ();

BankAccount.java

47

CashRegister.java

package cs160 ; public class CashRegister { public static final double QUARTER_VALUE = 0.25

, DIME_VALUE = 0.1

, N ICKEL_VALUE = 0.05

, PENNY_VALUE = 0.01

; private double purchase , payment ; public CashRegister () { purchase = 0 ; payment = 0 ;

} public void recordPurchase ( double amount ){ purchase = purchase + amount ;

} public void receivePayment ( int dollars , int quarters , int dimes , int nickels , int pennies ) { payment = dollars + quarters * QUARTER_VALUE + dimes * DIME_VALUE

+ nickels * NICKEL_VALUE + pennies * PENNY_VALUE ;

} public double giveChange (){ double change = payment purchase ; purchase = 0 ; payment = 0 ; return change ;

} public static void main ( String [] args ){

CashRegister register = new CashRegister (); register .

recordPurchase ( 0.75

); register .

recordPurchase ( 1.50

); register .

receivePayment ( 2 , 0 , 5 , 0 , 0 );

System .

out .

print ( "Change: " );

System .

out .

println ( register .

giveChange ());

System .

out .

println ( "Expected: 0.25" );

}

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

48

 Add package to jar file list

1. Create the jar file

• In the shell prompt (in parent directory of cs160/ch8) type jar cvf cs160.jar cs160/ch8/*.class

2. Add jar to classpath in DrJava:

• Edit  Preferences  ResourceLocations  ExtraClassPath  Add  select cs160.jar  ok

Copyright © 2014 by John Wiley & Sons. All rights reserved.

49

Importing Packages

 Can use a class without importing : refer to it by its full name (package name plus class name): java.util.Scanner in = new java.util.Scanner(System.in);

• Inconvenient

 import directive lets you refer to a class of a package by its class name, without the package prefix : import java.util.Scanner;

• Now you can refer to the class as Scanner without the package prefix.

• E.g. Scanner in = new Scanner(System.in);

Copyright © 2014 by John Wiley & Sons. All rights reserved.

50

Importing Packages

 Can import all classes in a package: import java.util.*;

 Never need to import java.lang

.

 You don't need to import other classes in the same package .

Copyright © 2014 by John Wiley & Sons. All rights reserved.

51

Programming Question

 Import packages:

• Write a tester class called PackageImportDemo which will test importing packages (save this class in a completely different location than the location you have source/.class files for cs160 package you created)

• Import the package you created and test BankAccount class by creating a BankAccount object with balance $1000 and printing the balance by calling toString() method:

Copyright © 2014 by John Wiley & Sons. All rights reserved.

52

Answer

PackageImportDemo.java

import cs160.ch8.BankAccount; public class PackageImportDemo

{ public static void main(String args[])

{

BankAccount acct = new BankAccount(1000.0);

System.out.println(acct);

}

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

53

Unit Test Framework

 Compilers cannot check for logical errors:

• whether the results of a program or method are correct.

 So how do you check those errors?

• Developers need to test their programs to ensure that they behave as expected.

• (+) Sometimes it is simple:

• calling a method in the Interactions Pane to view its results

• (-) Developer should know expected answers.

 A better solution:

• Give the tests the answers you expect, and let the tests themselves do all the work .

Copyright © 2014 by John Wiley & Sons. All rights reserved.

54

 Unit testing makes this quite easy.

 Unit testing is the testing of single entity (class or method)

 Fast Automation:

• runs test cases significantly faster than human resources.

 You write many small tests that create your objects and assert that they behave the way you expect in different situations.

 A unit test framework known as JUnit ( http://www.junit.org

) automates the process of running these tests , letting you quickly see whether your program returns the results you expect.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

55

JUnit

 JUnit : http://junit.org

• A unit testing framework for the Java Programming Language

• Idea: "first testing then coding“

• Open source framework used for writing & running tests.

• Unit tests can be run automatically and they check their own results and provide immediate feedback.

• Shows test progress in a bar that is green if test is going fine and it turns red when a test fails.

• Built into some IDEs like BlueJ ,Eclipse and DrJava

• DrJava Junit documentation:

• http://www.drjava.org/docs/user/ch07.html

Copyright © 2014 by John Wiley & Sons. All rights reserved.

56

JUnit

 Philosophy:

• Whenever you implement a class, also make a companion test class.

• Run all tests whenever you change your code.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

57

JUnit

 In DrJava:

1. Write a JUnit test class

2. Test Current junit test case Document:

• Choose the "Test Current Document" command from the Tools menu to run the tests and view the results.

Test all open junit test case documents :

• C lick the "Test" button on the toolbar or choo "Test All Documents" from the Tools menu

 Output:

• Shown in the Test Output tab

• Each test method turn green if it completes successfully and red if it fails.

• A progress bar will keep you updated on how many tests have been run.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

58

JUnit

 Unit tests are any public classes that extend the junit.framework.TestCase

class

 Have any number of methods with names beginning with the word " test “

Copyright © 2014 by John Wiley & Sons. All rights reserved.

59

JUnit

 Writing a Test Case:

 Choose the "New JUnit Test Case" command from the File menu

 This automatically generate a template with these conventions.

 At the top of the file, include:

• import junit.framework.TestCase;

 The main class of the file must:

• be public

• extend TestCase

Copyright © 2014 by John Wiley & Sons. All rights reserved.

60

JUnit

 Methods of this class to be run automatically when the Test command is invoked must:

• be public and not static

• return void

• take no arguments

• have a name beginning with "test“

 Test methods in this class can call any of the following methods (among others):

• void assertTrue (String, boolean)

• issues an error report with the given string if the boolean is false.

• void assertEquals (String, int, int)

• issues an error report with the given string if the two integers are not equal. The first int is the expected value, and the second int is the actual (tested) value.

• void fail (String)

• which immediately causes the test to fail, issuing an error report with the given string.

Copyright © 2014 by John Wiley & Sons. All rights reserved.

61

Simple Test Example

 Simple Test Example

 Suppose you are writing a Calculator class that can perform simple operations on pairs of integers.

 First write testcase class with few tests for it

 Then write the Calculator class

 Compile both classes

 Run the tests to see if they pass

• “Tools  Test current document”

Copyright © 2014 by John Wiley & Sons. All rights reserved.

62

CaclulatorTest.java

import junit .

framework .

TestCase ; public class CalculatorTest extends TestCase

{ public void testAddition ()

{

Calculator calc = new Calculator ();

// 3 + 4 = 7 int expected = 7 ; int actual = calc .

add ( 3 , 4 ); assertEquals ( "adding 3 and 4" , expected , actual );

}

{ public void testDivision ()

Calculator calc = new Calculator ();

// Divide by zero shouldn't work try

{ calc .

divide ( 2 , 0 ); fail ( "Should have thrown an exception!" );

} catch ( ArithmeticException e ) {

}

// Good, that's what we expect

}

}

Copyright © 2014 by John Wiley & Sons. All rights reserved.

Caclulator.java

public class Calculator

{ public int add ( int a , int b )

{ return a + b ;

} public int divide ( int a , int b )

{ return a / b ;

}

}

63