This is a set of "slides" to accompany chapter 12 of Timothy Budd's textbook Understanding Object-Oriented Programming with Java (Addison-Wesley, 1998).
Term used in several different ways in computer science
Polymorphism is a trivial issue in untyped languages
All variables are potentially polymorphic
Variables take on the type of their values dynamically
silly: x " a silly Smalltalk polymorphic method " (x isKindOf: Integer) ifTrue: [ ^ x + 1 ] . (x isKindOf: Fraction) ifTrue: [ ^ x reciprocal ] . (x isKindOf: String) ifTrue: [ ^ x reversed ] . ^ nil
Variable declared as one class can hold values from subclass
A single function name denoting two or more function bodies is overloaded
+
means both integer and floating
addition
In Java, +
also used for string concatenation
class Spouse { public void sendFlowersTo(Address anAddress) { go to florist; give florist message sendFlowersTo(anAddress); } } class Florist { public void sendFlowersTo(Address anAddress); { if (address is nearby) { make up flower arrangement; tell delivery person sendFlowersTo(anAddress); } else { look up florist near anAddress; contact other florist; give other florist message sendFlowersTo(anAddress); } } }
sendFlowersTo
methods are semantically
related but not related via inheritance
-- the number, types, and order of parameters
-- parametric overloading
Polymorphic Symbol <<
used for both left shift and
stream output -- latter also overloaded by type of value
stream << integer; stream << char; stream << char *; stream << double; stream << complex;
Overriding occurs when child class changes meaning of function from parent
abstract class Magnitude { public boolean lessOrEqual(Magnitude arg) throws IncomparableMagnitudeException { return (this.lessThan(arg) || this.equals(arg)); } public boolean greaterOrEqual(Magnitude arg) throws IncomparableMagnitudeException { return arg.lessOrEqual(this); } public boolean lessThan(Magnitude arg) throws IncomparableMagnitudeException { return this.lessOrEqual(arg) && ! this.equals(arg); } public boolean greaterThan(Magnitude arg) throws IncomparableMagnitudeException { return arg.lessThan(this); } } class IncomparableMagnitudeException extends Exception { public IncomparableMagnitudeException() { } public IncomparableMagnitudeException(String msg) { super(msg); } }
To define all six comparisons in a noncircular manner, subclasses must:
Object
method equals()
if default not appropriate
Magnitude
method
lessThan()
or lessOrEqual()
class Point extends Magnitude { public Point(int x0, int y0) { x = x0; y = y0; } public boolean lessThan(Magnitude arg) throws IncomparableMagnitudeException { if (arg instanceof Point) { Point p = (Point) arg; // less if lower left quadrant return x < p.x && y < p.y; // of this point } else throw new IncomparableMagnitudeException(); } private int x; private int y; }
Note: The above method uses inheritance by limitation because of the
check for the Point
type and throwing the exception
Semantics of abstract methods should be specified carefully -- e.g., using pre- and postconditions
Subclasses should adhere to specification
abstract
modifier for method
between
(like the other methods of
Magnitude
) exhibits pure polymorphism
class Magnitude { ... public boolean between(Magnitude low, Magnitude high) throws IncomparableMagnitudeException { return low.lessOrEqual(this) && this.lessOrEqual(high); } }
Works for any receiver or arguments of parent type
Magnitude
(generates exception if of incomparable types)
Is Between
"
Point p = new Point(0,0); Point q = new Point(10,10); Magnitude r = new Point(0,0); if (r.between(p,q)) System.println("Is Between"); else System.println("Is Not Between");
Message r.between(p,q)
has the following trace of dynamic
binding:
between()
in
Point
, not found
between()
in
Magnitude
, found, binds call
Magnitude.between
, checks for
lessOrEqual()
in Point
, not found
Magnitude.between
, checks for
lessOrEqual()
in Magnitude
, found, binds
call
Magnitude.lessOrEqual
, checks for
lessThan()
in Point
, found, binds call
Point.lessThan
, returns false
since (0,0) is not less than (0,0)
Magnitude.lessOrEqual
, checks for
equals()
in Point
, not found
Magnitude.lessOrEqual
, checks for
equals()
in Magnitude
, not found
Magnitude.lessOrEqual
, checks for
equals()
in Object
, found, binds call
Object.equals
, returns true
Magnitude.lessOrEqual
, returns true
since (0,0) <= (0,0)
Magnitude.between
, returns true
since (0,0) <= (0,0) and (0,0) <= (10,10), l
C++ example:
template <class T> class Link { public: ... private: T value; Link* nextLink; }
Link<Shape> sl;
Declaration above makes s1
a Link
variable
that has a value
of type Shape
Keyword generic
reserved
Experimental versions of Java do support generics
extends
)
implements
)
final
prevents overriding
abstract
for deferred methods, signature
but no body
UP to CSCI 581 Lecture Notes root document?