lecture 8: object-oriented design. 8-2 microsoftintroducing cs using.netj# in visual studio.net...
TRANSCRIPT
Lecture 8:
Object-Oriented Design
8-2MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Objectives
“Good object-oriented programming is really about good object-oriented design. And good OOD is all about making things easier for ourselves, as well as for our class users…”
• Class design• Inheritance• Interfaces
8-3MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Part 1
• Class design…
8-4MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Class design rules #1 – #4
• These rules you probably already know:
1. "Classes should provide constructors" – to ensure initialization of fields
2. "Classes should provide methods to manipulate class fields"– e.g. bank Customer's getFormattedBalance( ) or makeDeposit(amt)
3. "Classes should practice data-hiding, and control access otherwise"– use of private keyword, get & set methods for field access
4. "Classes should override toString( )"– to return appropriate string-based representation
8-5MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Class design rule #5
• "Classes should override Equals( )"– enables object equality to be determined based on fields
• Example:– students are equal if their IDs are the same
public class Student{ private int id; . . . public boolean equals(Object obj) { // make sure we are comparing apples to apples… if (obj == null || !(obj.getClass().equals(this.getClass()))) return false;
// we know obj is a student but J# doesn't, so type-cast to Student so we can compare IDs… Student other = (Student) obj; return this.id == other.id; }
public class Student{ private int id; . . . public boolean equals(Object obj) { // make sure we are comparing apples to apples… if (obj == null || !(obj.getClass().equals(this.getClass()))) return false;
// we know obj is a student but J# doesn't, so type-cast to Student so we can compare IDs… Student other = (Student) obj; return this.id == other.id; }
if (s1.equals(s2)) ...if (s1.equals(s2)) ...
8-6MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Class design rule #6
• "Classes that override Equals( ) should also override hashCode( )"– Java rule: equal objects must have equal hash codes
– Solution? Base hashCode( ) on same field(s) as equals( )
• Example:– student's hash code is their ID!
public class Student{ private int id; . . .
public int hashCode() { return this.id; // equal students will have same hash code! }
public class Student{ private int id; . . .
public int hashCode() { return this.id; // equal students will have same hash code! }
8-7MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Part 2
• Inheritance…
8-8MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Inheritance
• One class may extend another class, inheriting all fields & methods:
• Why do this?
– Code reuse! Class B doesn't have to reinvent class A…
– Design reuse! Class B "is-a" class A, and treated as such…
public class B extends A{ . . .}
public class B extends A{ . . .}
8-9MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Example
Student
firstName : StringlastName : Stringid : intgpa : double
Student(fn, ln, id, gpa)get_firstName( ) : String . . .
Freshman
Sophomore
Junior
Senior
super / base / parent
sub / derived / child
• Student class hierarchy:
extends
8-10MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Superclass design
• Superclass can define members as private, protected, or public • Superclass can define common functionality for its subclasses
• Superclass can define abstract methods for subclasses to implement
public abstract class Student{ protected String firstName, lastName; protected int id; protected double gpa; . . .
public String getFormattedGPA() { java.text.DecimalFormat formatter; formatter = new java.text.DecimalFormat("0.00"); return formatter.format(this.gpa); }
public abstract boolean meetsMinGPA();}
public abstract class Student{ protected String firstName, lastName; protected int id; protected double gpa; . . .
public String getFormattedGPA() { java.text.DecimalFormat formatter; formatter = new java.text.DecimalFormat("0.00"); return formatter.format(this.gpa); }
public abstract boolean meetsMinGPA();}
8-11MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Subclass design
• Subclasses are responsible for:– calling their superclass's constructor– implementing any abstract methods
public class Freshman extends Student{ public Freshman(String fn, String ln, int id, double gpa) { super(fn, ln, id, gpa); }
public boolean meetsMinGPA() { // freshman must maintain a GPA of 1.5 or greater... return this.gpa >= 1.5; }}
public class Freshman extends Student{ public Freshman(String fn, String ln, int id, double gpa) { super(fn, ln, id, gpa); }
public boolean meetsMinGPA() { // freshman must maintain a GPA of 1.5 or greater... return this.gpa >= 1.5; }}
8-12MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Polymorphism
• Poly-whatism?• Polymorphism is about writing code in a general way
– the more general the code, the more reusable in new situations
• More formally:– Definition: polymorphism is when different types support the
same operation, allowing the types to be treated similarly.– this allows the same code to work on a wider range of types
• Example?– Student objects and meetsMinGPA( )
– next page…
8-13MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Example: meetsMinGPA( )
• meetsMinGPA() is an example of a polymorphic method– defined in super class so all students support it– implemented in subclasses so each implementation may differ
• Advantage?– the following code correctly checks *all* types of students to
ensure they are meeting minimum GPA requirements!
java.util.ArrayList students = new java.util.ArrayList();students.add( new Freshman(…) ); // a Freshman is-a Student…students.add( new Junior(…) ); // a Junior is-a Student… . . .
for (int i = 0; i < students.size(); i++){ Student s = (Student) students.get(i); if (!s.meetsMinGPA()) System.out.println("Min GPA violation: " + s);}//for
java.util.ArrayList students = new java.util.ArrayList();students.add( new Freshman(…) ); // a Freshman is-a Student…students.add( new Junior(…) ); // a Junior is-a Student… . . .
for (int i = 0; i < students.size(); i++){ Student s = (Student) students.get(i); if (!s.meetsMinGPA()) System.out.println("Min GPA violation: " + s);}//for
8-14MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
.
.
.
for (int i = 0; i < students.size(); i++){ Student s = (Student) students.get(i); if (!s.meetsMinGPA())
.
.
.
for (int i = 0; i < students.size(); i++){ Student s = (Student) students.get(i); if (!s.meetsMinGPA())
Dynamic binding
• Dynamic binding is the technology that enables polymorphism• When you make a method call:
1. Java dynamically determines the type of the object, then
2. Java binds to ("calls") the correct method based on object's type
(1) What type of object: Freshman, Sophomore, Junior, or Senior?
(2) Based on answer to (1), dynamically bind to (i.e. "call") the correct implementation of the meetsMinGPA( ) method in Freshman, Sophomore, Junior, or Senior.
8-15MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Overriding equals, part 2
• Problem:– suppose we override equals( ) as discussed earlier, which
requires that objects be exactly the same type to be equal– in this case, how do we search for students?
java.util.ArrayList students = new java.util.ArrayList(); . . .
int loc, id;Student s;id = ...; // id of student we are looking for…s = new ????????? ("", "", id, 0.0); // create temp object for search
loc = students.indexOf(s); // linear search for actual student…
java.util.ArrayList students = new java.util.ArrayList(); . . .
int loc, id;Student s;id = ...; // id of student we are looking for…s = new ????????? ("", "", id, 0.0); // create temp object for search
loc = students.indexOf(s); // linear search for actual student…
What class do we use?
8-16MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Overriding equals again…
• Instead of requiring exactly the same types, check to make sure both objects inherit from Student…
– we know "this" object does, just a matter of checking "obj"…
public abstract class Student{ private int id; . . . public boolean equals(Object obj) { // make sure we are comparing apples to apples… if (obj == null || !(obj.getClass().equals(this.getClass()))) return false;
// we know obj is a student but J# doesn't, so type-cast to Student so we can compare IDs… Student other = (Student) obj; return this.id == other.id; }
public abstract class Student{ private int id; . . . public boolean equals(Object obj) { // make sure we are comparing apples to apples… if (obj == null || !(obj.getClass().equals(this.getClass()))) return false;
// we know obj is a student but J# doesn't, so type-cast to Student so we can compare IDs… Student other = (Student) obj; return this.id == other.id; }
!(obj instanceof Student))
8-17MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Linear search again…
• Now you can search by creating any kind of object you want:– except for Student, which won't work since it's abstract
java.util.ArrayList students = new java.util.ArrayList(); . . .
int loc, id;Student s;id = ...; // id of student we are looking for…s = new Senior("", "", id, 0.0); // create temp object for search
loc = students.indexOf(s); // linear search for actual student…if (loc >= 0) System.out.println("Found at location " + loc);
java.util.ArrayList students = new java.util.ArrayList(); . . .
int loc, id;Student s;id = ...; // id of student we are looking for…s = new Senior("", "", id, 0.0); // create temp object for search
loc = students.indexOf(s); // linear search for actual student…if (loc >= 0) System.out.println("Found at location " + loc);
8-18MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Part 3
• Interfaces & design by contract…
8-19MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Motivation
• We program by relying on "contracts"– i.e. agreements between objects– "Object X agrees to do Y, so I'll call X when I need to do Y"
java.io.FileReader file = new java.io.FileReader("…");java.io.BufferedReader reader = new java.io.BufferedReader(file);
s = reader.readLine();
java.io.FileReader file = new java.io.FileReader("…");java.io.BufferedReader reader = new java.io.BufferedReader(file);
s = reader.readLine();
public class BufferedReader{ . . .
public String readLine() { . . . }
public class BufferedReader{ . . .
public String readLine() { . . . }
8-20MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Design by contract
• Design by contract formalizes this process– design first– implement second
• Advantages?
– encourages "think before you code"
– ensures integration of classes in a large program
– different classes supporting the same contract offer another means of polymorphic programming!
8-21MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Interfaces
• Interfaces are a formal way of specifying contracts• An interface = a set of method signatures
– representing the contract between two or more parties– pure design, no data / code
public interface SomeInterfaceName{ public void Method1(); public int Method2(int x, String y); . . .}
public interface SomeInterfaceName{ public void Method1(); public int Method2(int x, String y); . . .}
8-22MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Conceptual view
• Here's how to visualize what's going on:
"server"(object performing
service according to interface contract)
"client"(object requesting
service)
Interface
– "client" uses interface to communicate with server– "server" implements interface to fulfill contract
8-23MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Example
• Sorting and binary search• These algorithms are a part of the Java Class Library
– but use an interface to communicate with objects…
sort( ) objectobjectobject
binarySearch( ) objectobjectobject
8-24MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
(1) Comparable interface
• Defines the comparison of two objects, returning an integer:– < 0 means this object < obj– = 0 means this object = obj– > 0 means this object > obj
public interface Comparable{ public int compareTo(Object obj);}
public interface Comparable{ public int compareTo(Object obj);}
if (s1.compareTo(s2) < 0) ...if (s1.compareTo(s2) < 0) ...
8-25MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
(2) Objects implement Comparable
• To fulfill contract, objects must implement Comparable:
public abstract class Student implements Comparable{ private int id; . . .
public int compareTo(Object obj) { // make sure we are comparing apples to apples… Student other = (Student) obj; if (this.id < other.id) return -1; else if (this.id == other.id) return 0; else return 1; }
public abstract class Student implements Comparable{ private int id; . . .
public int compareTo(Object obj) { // make sure we are comparing apples to apples… Student other = (Student) obj; if (this.id < other.id) return -1; else if (this.id == other.id) return 0; else return 1; }
studentstudentstudent
8-26MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
(3) Call sort() and binarySearch()
• Now we can take advantage of these built-in algorithms:
java.util.ArrayList students = new java.util.ArrayList();students.add( new Freshman(…) );students.add( new Junior(…) ); . . .
java.util.Collections.sort(students);
int loc, id;Student s;id = ...; // id of student we are looking for…s = new Senior("", "", id, 0.0); // create temp object for search
loc = java.util.Collections.binarySearch(students, s);if (loc >= 0) System.out.println("Found at location " + loc);
java.util.ArrayList students = new java.util.ArrayList();students.add( new Freshman(…) );students.add( new Junior(…) ); . . .
java.util.Collections.sort(students);
int loc, id;Student s;id = ...; // id of student we are looking for…s = new Senior("", "", id, 0.0); // create temp object for search
loc = java.util.Collections.binarySearch(students, s);if (loc >= 0) System.out.println("Found at location " + loc);
8-27MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET
Summary
• Good OOP is all about good Object-Oriented Design• Java, J# and .NET all employ a great deal of OOD
– effective use requires a solid understanding of OOD
– e.g. linear search is built-in, but you need to implement equals()
– e.g. sorting & binary search are built-in, but you need to implement Comparable and compareTo()
• Inheritance & interfaces are important OOD tools
– look for ways to create / exploit polymorphism