chapter9 - Chapter 9 Designing Classes Goals Learning to...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: Chapter 9 Designing Classes Goals Learning to design classes Preconditions and postconditions for methods More details about static/class methods and fields Creating packages Division of labor: Choosing Classes Methods = functions Classes/objects = entities A class represents a single concept from the problem domain Name for a class should be a noun that describes a concept Good Classes Concepts from mathematics: Point Rectangle Ellipse Path Concepts from real life BankAccount CashRegister Bus Taxi Good Classes Actors (end in er, or) objects that do some kind of work for you Scanner Random // better name: RandomNumberGenerator Utility classes no objects, only static methods and constants Math Degenerate case of a class: only main() method Bad Classes Don't turn actions into classes: Paycheck is better name than ComputePaycheck The name can tip you off when you are on wrong track Representing a pay check is more useful than only designing a class that seems to compute a pay check OOP Class Diagram The name of the class appears at the top ClassName -privatedata +public data -private constructors +public constructors -privatem thods e +public m thods e fields constructors and methods Practice Question class Die What aretheoperations ne de to usethe e d die ? What data arene de to re se theconce e d pre nt pt of a die ? class Die Die -side s:int -top:int +roll():void +ge tTop():int Design Questions How might I design a soccer game? 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 methods and public constants/variables should all relate to the central idea of the class This class lacks cohesion: Cohesion public class CashRegister{ public void enterPayment(int dollars, int quarters, int dimes, int nickels, int pennies) . . . public public public . . . } static static static final final final double double double NICKEL_VALUE = 0.05; DIME_VALUE = 0.1; QUARTER_VALUE = 0.25; Cohesion What is the problem with this class? More confusion Ties the role of a cash register to the value of the coins What if we wanted to sell this cash register to other countries? CashRegister, as described above, involves two Solution concepts: cash register and coin Solution: Make two classes: public class Coin{ public Coin(double aValue, String aName){ . . . } public double getValue(){ . . . } . . . } public class CashRegister{ public void enterPayment(int coinCount, Coin coinType) { . . . } . . . } A class depends on another if it uses objects of that class depends on Coin to determine the value of the payment CashRegister Coin does not depend on CashRegister Coupling High coupling = many class dependencies Coupling Minimize coupling to minimize the impact of interface changes To visualize relationships draw class diagrams UML: Unified Modeling Language. Notation for objectoriented analysis and design Questions How can we modify the BankAccount class to maintain information about the customer? How might we minimize coupling with the Soccer game example? Immutable Classes Recall that accessor methods only retrieve information They do not change the state of the object Calling them multiple times in a row will yield same results Immutable classes are classes that only have accessor methods Immutable Classes Example: String Class Advantages Do not have to worry about the dangers of handing off references in methods Have to create a new object whenever you want the data to look different Disadvantages Mutable Classes Most classes are mutable they do have mutator methods Bus, Taxi, Path, BankAccount are all mutable StringBuffer can be used if you want to store strings that you can mutate Mutators are designed to change the internal data of the implicit parameter Side effect of a method: modifying externally observable data (explicit parameters) Side Effects public void transfer(double amount, BankAccount other) { balance = balance - amount; other.balance = other.balance + amount; // Modifies explicit parameter } Side Effects Updating an explicit parameter can be surprising to programmers, and it is best to avoid it if possible Other Side Effects Why don't we add a printBalance() method to BankAccount? public void printBalance() // Not recommended { System.out.println("The balance is now $" + balance); } Other Side Effects Makes potentially dangerous assumptions The BankAccount class will only be used in English speaking country The machine using the program has a System.out association An instance of too much coupling Minimizing Side Effects Never modify explicit parameters to a method Treat them as constants public void deposit(double amount) { balance = amount + balance; } Passing Parameters Two ways to pass parameters Pass by reference the memory location is sent, meaning that the data can be changed Pass by value a copy of the memory location is created Java only uses pass by value Even objects are passed by value, since the reference is copied Example public class BankAccount{ public void trasnfer(double amount, BankAccount other) { balance = balance amount; double newBalance = other.balance + amount; other = new BankAccount(newBalance); } } Does this work? Why or why not? Preconditions Precondition: Requirement that the caller of a method must meet Publish preconditions so the caller won't call methods with bad parameters /** Deposits money into this @param amount the amount (Precondition: amount >= */ account. of money to deposit 0) Preconditions 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 If precondition is violated, the method is not responsible for computing the correct result. It is free to do anything. Example What preconditions are needed for dropOffPassenger() in the Taxi class? What a is precondition to next() in Scanner? Handling Violations Method does not have to behave correctly when preconditions are violated But what should be done? Assume data is correct. Only a corruption/crashes to happen at fault of user Throw an exception if a condition is violated. The control is shifted to an exception handler Runtime error messages are all exceptions Handling Violations Both have their disadvantages Exceptions slow down the program Doing nothing can be very dangerous Best of both worlds: assertions that can be turned on or off Assertions Method can do an assertion check assert amount >= 0; balance = balance + amount; To enable assertion checking: java -enableassertions MyProg You can turn assertions off after you have tested your program, so that it runs at maximum speed Common Error Returning silently on an error is hard to detect and debug if (amount < 0) return; // Not recommended; hard to debug balance = balance + amount; Postconditions Postcondition: a condition that is true after a method has completed. This is the designer's duties (recall preconditions are the user's duty) If method call is in accordance with preconditions, it must ensure that postconditions are valid Postconditions There are two kinds of postconditions: The return value is computed correctly The object is in a certain state after the method call is completed (mutators) /** Deposits money into this account. (Postcondition: getBalance() >= 0) @param amount the amount of money to deposit (Precondition: amount >= 0) */ Postconditions Don't document trivial postconditions that repeat the @return clause Formulate pre and postconditions only in terms of the interface of the class amount <= getBalance() // this is the way to state a postcondition amount <= balance // wrong postcondition formulation Contract Think of pre and postconditions as a contract If caller fulfills the precondition, the method must fulfill the postcondition. Static (Class) Fields Stores a field outside of any particular instance (object) Only one copy of a field that is shared by all instances of a class Usually minimize the use of static for object oriented programs Static (Class) Methods Can be invoked without creating an instance. Can only access explicit parameters, class fields, class methods and constructors. main method must be static Field Modifier Choices For each field: 1. 2. 3. 4. Choose identifier and data type. Is it a constant? If so, add final modifier Does it require a different value for each instance? If not, add static modifier Is it safe to be directly accessible to methods in other classes? o If so, public Else private 5. Is the static value known? If so, initialize to that value For each method: 1. 2. Method Modifier Choices Choose identifier, return type, and parameters Does it access any instance (nonstatic) fields or instance methods? Must it be called from methods in other classes? o If not, add static modifier If so, must be public Else make it private 3. 4. Is it safe to be overridden? (inheritance) If not, add final modifier Static (Class) Fields Why make fields static? so that only one copy of the value is stored (all instances share the same copy) Static Methods Why make methods static? So that the method is accessible without creating an instance Note: We can only do this if the method only requires explicit parameters or static fields. Static Methods Why write a method that does not operate on an object? Common reason: we're encapsulating some computation that involves only numbers. Numbers aren't objects, you can't invoke methods on them. E.g., x.sqrt() is not legal in Java Static Methods: Example public class Financial { public static double percentOf(double p, double a) { return (p / 100) * a; } // More financial methods can be added here. } Static Methods: Example Call with class name instead of object: double tax = Financial.percentOf(taxRate, total); main is static there aren't any objects yet Three ways to initialize: Do nothing. Field is 0 (for numbers), false (for boolean values), or null (for objects) Use an explicit initializer, such as Static Fields public class BankAccount { . . . private static int lastAssignedNumber = 1000; // Executed once, when class is loaded } Use a static initialization block Scope Scope of a variable: Region of program in which the variable can be accessed Scope of a local variable extends from its declaration to end of the block that encloses it Sometimes the same variable name is used in two methods. Scope: Example public class RectangleTester { public static double area(Rectangle rect) { double r = rect.getWidth() * rect.getHeight(); return r; } public static void main(String args) { Rectangle r = new Rectangle(5, 10, 20, 30); double a = area(r); System.out.println(r); } } Scope The scope of a local variable cannot contain the definition of another variable with the same name Rectangle r = new Rectangle(5, 10, 20, 30); if (x >= 0) { double r = Math.sqrt(x); // Errorcan't declare another variable //called r here . . . } Scope However, we can have local variables with identical names if scopes do not overlap if (x >= 0) { double r = Math.sqrt(x); . . . } // Scope of r ends here else { Rectangle r = new Rectangle(5, 10, 20, 30); // OKit is legal to declare another r here . . . } Scope private members have class scope: You can access all members in any method of the class Must qualify public members outside scope Math.PI harrysChecking.BANK_FEE Scope Inside a method, there is no need to qualify fields or methods that belong to the same class An unqualified instance field or method name automatically refers to the current object (this) public class BankAccount { public void transfer(double amount, BankAccount other) { withdraw(amount); // this.withdraw(amount); other.deposit(amount); } . . . } A local variable can shadow a field with the same name Local scope wins over class scope Scope public class Coin { . . . public double getExchangeValue(double exchangeRate) { double value; // Local variable . . . return value; } private String name; private double value; // Field with the same // name } Scope Access shadowed fields by qualifying them with the this reference value = this.value * exchangeRate; Packages A package is a set of related classes To put classes in a package, you must place a line package <packageName>; as the first instruction in the source file containing the classes The package name consists of one or more identifiers separated by periods Packages For example, to put the Financial class introduced into a package named com.horstmann.bigjava, the file must start as follows: package com.horstmann.bigjava; public class Financial { . . . } Packages: Default The default package has no name and thus no package statement ...
View Full Document

This note was uploaded on 08/08/2008 for the course CS 302 taught by Professor Willbenton during the Spring '07 term at Wisconsin.

Ask a homework question - tutors are online