Chapter 7 PowerPoint presentation here

Download Report

Transcript Chapter 7 PowerPoint presentation here

Chapter 7
Designing Classes
Chapter Goals
 To learn how to choose appropriate classes to
implement
 To understand the concepts of cohesion and
coupling
 To minimize the use of side effects
 To document the responsibilities of methods and
their callers with preconditions and
postconditions
 To understand the difference between instance
methods and static methods
 To introduce the concept of static fields
 To understand the scope rules for local
variables and instance fields
 To learn about packages
Choosing Classes
 A class represents a single concept
 Concepts from mathematics:
Point
Rectangle
Ellipse
 Concepts from real life
BankAccount
Purse
 Actors (end in -er, -or)
StringTokenizer
Random (better called RandomNumberGenerator)
 Utility classes--no objects, only static methods
Math
Cohesion
 Cohesive = public interface closely related to the single
concept that the class represents
 This class lacks cohesion:
– public class Purse
{
public Purse(){...}
public void addNickels(int count){...}
public void addDimes(int count){...}
public void addQuarters(int count){...}
public double getTotal(){...}
public static final double NICKEL_VALUE =0.05;
public static final double DIME_VALUE =0.1;
public static final double QUARTER_VALUE =0.25; ...
}
Cohesion
 Two concepts: purse and coin
 Solution: Make two classes:
– public class Coin
{
public Coin(double aValue,String aName){...}
public double getValue(){...}
}
public class Purse
{
public Purse(){...}
public void add(Coin aCoin){...}
public double getTotal(){...}
}
Coupling
 A class depends on another if it calls one
of its methods
 Purse depends on Coin because it calls
getValue on coins
 Coin does not depend on Purse
 High Coupling = many class
dependencies
 Minimize coupling to minimize the
impact of interface changes
Dependency Relationship between
Purse and Coin Classes
High and Low Coupling
between Classes
Accessor and Mutator Classes
 Accessor: does not change the state of the
implicit parameter (e.g. getBalance)
 Mutator: changes the state of the implicit
parameter (e.g. deposit )
 Rule of thumb: Mutator should return
void
 Immutable class: all methods are
accessors (e.g. String)
Side Effect
• Side Effect: any observable change outside
the implicit parameter Example: modify
explicit parameter
• public void transfer(double amount,
BankAccount other)
{
balance = balance - amount;
other.balance = other.balance + amount;
}
• Example: printing in method
• public void deposit(double amount)
{
if (amount < 0)
System.out.println("Bad value");
...
}
• Reprehensible: couples with System, PrintStrea
Common Error: Can't Modify
Primitive Type Parameters
• void transfer(double amount, double
otherBalance)
{
balance = balance - amount;
otherBalance = otherBalance + amount;
}
• Won't work Scenario:
• double savingsBalance = 1000;
harrysChecking.transfer(500,
savingsBalance)
Modifying a Numeric Parameter
has No Effect on Caller
Preconditions
 Publish preconditions so the caller won't call
methods with bad parameters
/**
Deposits money into this account.
@param amount the amount of money to deposit
(Precondition: amount >= 0)
*/
 Typical use:
 To restrict the parameters of a method
 To require that a method is only called when the
object is in an appropriate state
 Method can do anything if called when precondition
not fulfilled
Preconditions
• Method may throw exception if precondition violated
• if (amount < 0)
throw new IllegalArgumentException();
balance = balance + amount;
• Nicer to throw exception than to silently muddle
through
• if (amount < 0)
return; // don't do this
balance = balance + amount;
• Method doesn't have to test for precondition. (Test
may be costly)
• // no test--that's ok
// if this makes the balance negative,
// it's the caller's fault
balance = balance + amount
Postconditions
 Condition that's true after a method has completed.
– /**
Deposits money into this account.
(Postcondition: getBalance() >= 0)
@param amount the amount of money to deposit
(Precondition: amount >= 0)
*/
 Don't document trivial postconditions that repeat the
@return clause
 Contract: If caller fulfills precondition, method must
fulfill postcondition
Static Methods
 Every method must be in a class
 Some methods have no implicit parameter
 E.g. if all parameters are primitive
class Numeric
{ public static boolean
approxEqual(double x, double y)
{...
}
}
 Call with class name instead of object:
if (Numeric.approxEqual(a, b)) . . .
 main is static--there aren't any objects
yet
 Too many static methods are a sign of
too little OO
Static Fields
• One field per class
• public class BankAccount
{
...
private double balance;
private int accountNumber;
private static int lastAccountNumber;
}
• public BankAccount()
{
lastAssignedNumber++;
// increment static field
accountNumber = lastAssignedNumber;
// set instance field
}
• Minimize the use of static fields. (Static
final fields are ok.)
A Static Field and Instance Fields
Scope
 Scope of variable: region of program
where you can refer to the variable by its
name
 Local variable scope: from definition to
end of block
 Class scope: all methods of the class
 Must qualify public members outside
scope, e.g. Math.sqrt
 Overlapping scope: local scope wins over class
scope
– public class Coin
{
public void draw(Graphics2D g2)
{
String name = "SansSerif"; // local scope
g2.setFont(new Font(name, . . .)); // local
name
g2.drawString(this.name, . . .); // field name
}
private String name; // class scope
...
}
Packages
Package
Purpose
Sample Class
java.lang
Language support
Math
java.util
Utilities
Random
java.io
Input and output
PrintStream
java.awt
Abstract Windowing
Toolkit
Color
java.applet
Applets
Applet
java.net
Networking
Socket
java.sql
Database Access
ResultSet
javax.swing
Swing user interface
JButton
org.omg.CORBA Common Object Request ORB
Broker Architecture
Placing Classes into Packages
 To place classes in package, start file with
package packagename;
–package com.horstmann.bigjava;
public class Numeric
{
...
}
 Default package has no name, no package
statement
Importing Packages
• Can always use class without importing
• java.awt.Color backgroundColor
= new java.awt.Color(. . .);
• Tedious to use fully qualified name Import lets
you use shorter class name
• import java.awt.Color;
...
Color backgroundColor = new Color(. . .);
• Can import all classes in a package
• import java.awt.*;
• Never need to import java.lang
Package Names
• Package names should be unambiguous
Recommendation: start with reversed domain
name
org.omg.CORBA
com.horstmann.bigjava Path name should
match package name
com/horstmann/bigjava/Numeric.java Path
name starts with class path
export CLASSPATH=/home/walters:.
Base Directories and
Subdirectories for Packages