polymorphism static vs. dynamic binding 9-27-2013jsearlem/cs242/fa13/lectures/15.bindin… ·...
TRANSCRIPT
Polymorphism
Static vs. Dynamic Binding
9-27-2013
Inheritance & Polymorphism
Principle of Substitutability
Static vs. Dynamic Binding
Immutability
Calendars & Dates
HW#3 due Monday, October 7th
Reading Assignment: EJ2, Chapter 4, Item 15 Java Tutorial on Immutability
● How to create an immutable class
Map< String, List<Circle> > shapes =
new HashMap< String, List<Circle> >(); String name1 = "bubbles";
shapes.put(name1, new ArrayList<Circle>());
shapes.get(name1).add(new Circle(0.5f, 100, 100));
shapes.get(name1).add(new Circle(1.5f, 200, 50));
shapes.get(name1).add(new Circle(2.0f, 300, 25));
String name2 = "whirls";
shapes.put(name2, new LinkedList<Circle>());
shapes.get(name2).add(new Circle(50, 75));
Set<String> keysInMap = shapes.keySet();
for (String key : keysInMap) { System.out.println(key);
List<Circle> temp = shapes.get(key);
for (Circle c : temp)
System.out.println(“\t” + c);
}
System.out.println( shapes ); // what gets printed??
Circle
FilledCircle
Object
<<abstract>>
Shape
<<interface>>
Comparable
Point
IS-A
IS-A
IS-A
implements
implements
IS-A
polymorphic variable
T ref1 = new S(); // OK as long as every S is a T
principle of “substitutability”
basic idea: the type declared for a variable does not have to match exactly the type of what it refers to, as long as it’s a substitutable type
Circle c1 = new FilledCircle(…);
Object obj = new Circle(…);
instances of a substitutable class must possess all data fields associated with the parent class (may have more, of course) – subclasses satisfy this
instances of a substitutable class must implement (either by overriding or inheriting) all functionality defined for the parent class (can add functionality) – subclasses satisfy this as well
so, an instance of a subclass can mimic the behavior of the superclass, and should be “indistinguishable” from an instance of the superclass if substituted in a similar situation
static ≈ at compile-time
TVremote
TV-DVDremote
TV
TV-DVD
IS-A
OK
OK
OK
static ≈ at compile-time
TVremote
TV-DVDremote
TV
TV-DVD
IS-A
OK
OK
NOT OK !
TVremote
TV-DVDremote
TV
TV-DVD
IS-A
OK
OK
TVremote.ffw(); // not OK (compile-time error)
((TV-DVDremote)TVremote).ffw(); // OK
// the type matches at compile-time & the // method works at run-time
Current State
TVremote
TV-DVDremote
TV
TV-DVD
IS-A
OK
OK
TVremote.ffw(); // not OK
((TV-DVDremote)TVremote).ffw(); // not OK // the type matches at compile-time, but the // cast fails at run-time, so run-time error occurs
Current State
Circle
Object Object
IS-A OK
OK
Circle
FilledCircle
IS-A
FilledCircle
OK
Circle
Object Object
IS-A
OK
NOT OK !
Circle
FilledCircle
IS-A
FilledCircle
OK
Circle
Object Object
IS-A NOT OK !
Circle
FilledCircle
IS-A
FilledCircle OK
NOT OK !
Object x1 Object
IS-A
Circle
Object x1 = new Circle(…);
System.out.println( x1 );
// will call Circle.toString(), even though the
// type of reference x1 is Object
// uses dynamic method binding! // dynamic ≈ at run-time
Assume that a separate toString() is implemented for Circle & FilledCircle
Comparable y1 Object
IS-A
Circle Comparable y1 = new Circle(…);
Circle c2 = new Circle();
System.out.println( y1.compareTo(c2) );
// OK, since Circle is comparable
// will call Circle.compareTo <<interface>>
Comparable
implements
Place common operations and fields in the superclass
Use inheritance to model the “is-a” relationship
Use polymorphism, not type information
Don’t use inheritance unless all the inherited methods make sense
Example: a misuse of inheritance:
public class Point { … }
public class Circle extends Point {…}
tries to represent the center of the circle by inheriting (x,y), but
- a circle is NOT a point
- circles inherit all methods from Point (including ones that don’t make sense)
example: have a class Day; also want Holiday
public class Holiday extends Day
// seems to make sense
However, suppose that Day has a method advance(n) which changes the fields ahead (or behind) by n days
Then, application programmer can write: Holiday fourthOfJuly = new Holiday(7,4); fourthOfJuly.advance(10); // wrong!
Representing dates
We’ve been using the Date class in the
java.util package for simplicity, but there are some issues to consider
Many programs manipulate dates such as "Saturday, February 3, 2001"
Consider the Date class: Date now = new Date(); // constructs current date/time System.out.println(now.toString()); // prints date such as // Sat Feb 03 16:34:10 PST 2001
Date class encapsulates point in time
from Object-Oriented Design & Patterns, Horstmann, Chapter 3, 2006
a Date is a point in time
from Object-Oriented Design & Patterns, Horstmann, Chapter 3, 2006
boolean after(Date other)
boolean before(Date other)
int compareTo(Date other)
long getTime()
returns milliseconds since the epoch (1970-01-01 00:00:00 GMT)
void setTime(long n)
Are any methods missing that should be there?
from Object-Oriented Design & Patterns, Horstmann, Chapter 3, 2006
int getMonth() Deprecated. As of JDK version 1.1, replaced by Calendar.get(Calendar.MONTH).
design principle: avoid deprecated methods
Responsibility of determining day, month, year, weekday, etc. is handled by a Calendar class
from Object-Oriented Design & Patterns, Horstmann, Chapter 3, 2006
The Date class doesn't measure months, weekdays, etc.
That's the job of a calendar
A calendar assigns a name to a point in time
Many calendars in use:
Gregorian (Julian)
Contemporary: Hebrew, Arabic, Chinese
Historical: French Revolutionary, Mayan
from Object-Oriented Design & Patterns, Horstmann, Chapter 3, 2006
public abstract class Calendar
extends Object
implements Comparable<Calendar>, Cloneable, Serializable
static fields include: JANUARY, FEBRUARY, … , AM, PM, MONDAY, TUESDAY, …
methods include: equals(), hashCode(), toString(), compareTo(), getDate(), getTime(), getTimeZone(), …
public class GregorianCalendar extends Calendar
supports both Julian and Gregorian calendars
e.g.
GregorianCalendar CUcalendar = new GregorianCalendar();
cf. Effective Java 2, p. 73 key idea: if an object is immutable, then other classes using the object have no way to change the data in the object Immutable objects are simple. Immutable objects are inherently thread-safe. Therefore, immutable objects can be shared freely
examples: String BigInteger PhoneNumber
Note that java.awt.Point is not immutable, but it should be
1. No mutator methods
2. No methods can be overridden
3. Make all fields (instance variables) final
4. Make all fields private.
5. Ensure exclusive access to any mutable components
// Example: immutable points
public final class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; }
“final” here means cannot subclass Point
all fields are final, no external access
no field refers to a mutable object
public int getX()
{ return x; }
public int getY()
{ return y; }
public boolean equals(Object o) { … }
public int hashCode() { … }
public String toString() { … }
} // end class Point
Accessor functions only; no corresponding mutators (no ‘setters’)
equals(), hashCode(), toString() as recommended
if the object is supposed to be a constant, it should be immutable
if the object will be changed frequently, it should be mutable
if the object is very large, be careful if you opt for immutability (copying the object will be slow)
sets and other collections returned from a method should be immutable to preserve encapsulation