Chapter 12: Polymorphism
• polymorphism comes from the Greek root for “many forms”
• polymorphism is about how we can use different objects in the same place in our program, i.e., polymorphism depends on objects that are substitutable for one another
• In object-oriented languages, polymorphism results from:
– the is-a relationship of inheritance,
– the mechanisms of message passing, and
– concept of substitutability and polymorphic variables
• A polymorphic variable can hold many different types of values
– Example: “PinBallTarget target” can be assigned a “Hole”, “ScorePad”, etc.
• Object-oriented languages often restrict the types of values to being subclasses of the declared type of the variable.
• Pure polymorphism - a single function
(code body) can operate on data of any type.
Most
• overriding
• deferred methods / generics
• overloading / ad hoc polymorphism – multiple functions (code bodies) with the same name each handle a different data type
Least
• In dynamically-typed languages (e.g., Scheme) we can write one function that operate on data of any type:
(define (sum-of-squares x y)
(+ (square x) (square y) ) )
– neither the types of the formal parameters (x and y) or the result is known until run-time
– sum-of-squares is not even limited to operating on numeric types
– The only requires are that
• the square operator knows how to handle x’s and y’s type
• the + operator knows how to handle arguments of (square x)’s and
(square y)’s types (In Java, that could be two Strings!)
• Some OOP languages like Smalltalk are dynamically-typed and support pure polymorphism at the method level
• Multiple function bodies have the same name with each operating on different types of data
• This common name is said to be overloaded
• In strongly-typed language (i.e., Java), the compiler can often determine the appropriate function and generate only a single code sequence
• Different forms of overloading exist
– Overloading from separate classes: the same method name (or operator) is used by different classes that are not linked by inheritance (e.g, +, isEmpty())
– Parametric overloading: the same method name is used in the same class, but with different argument signatures
• All object-oriented languages permit the form of overloading
• Resolution of the overloaded name by the compiler is easy by observing the class of the receiver, e.g., myVector.isEmpty()
• Not bad programming style either if the name is meaningful in each class
• The meaning might be complete different (i.e., dissimilar) in each class, e.g.,
– “draw” in a card class, and
– “draw” in a circle class
• the same method name is used in the same class, but with different argument signatures
• Constructor methods often use parametric overloading, e.g., the Rectangle class
Rectangle()
Rectangle(int width, int height)
Rectangle(int width, int height, int x, int y)
Rectangle(Point origin)
Rectangle(Dimension widthAndHeight)
Rectangle(Point origin, Dimension widthAndHeight)
• Any method (not just constructors) can be overloaded as long as each method has a distinct argument signature
• The superclass has a general method, say doSomething(), but a subclass defines a method with the same name that hides access to the superclass’s method.
• Two different forms of overriding:
– replacement – code from the parent class is not executed at all
– refinement – parent’s code is executed from the subclasses code by using
“super.doSomething()”
• Parent class for numeric wrapper classes:
Integer, Long, Double, etc.
• Subclasses must override abstract methods public abstract class Number { public abstract int intValue(); public abstract long longValue(); public abstract float floatValue(); public abstract double doubleValue() public byte byteValue() {return (byte) intValue;} public short shortValue() { return (short) intValue();
}
} // end Number
• Many languages are statically-typed , that is, they require us to declare the type of a variable in our code. Ada generics and C++ templates are constructs that provide polymorphism of this sort, in a statically-typed way. Java 5.0
(aka Java 1.5) supports generic classes, too!
template <class Worker> public class Decorator {
Worker myInstanceVariable; public Worker getValue() { return myInstanceVariable; }
...
}
• This allows me to create decorators for objects of any type:
– Decorator<int>
– Decorator<Ball>
• This mechanism enables programmers to create nearly-pure polymorphism by declaring the kind of object that can be "wrapped".
The template gives enough information that the compiler can verify that the polymorphic behavior will exist at run-time.
• The use of polymorphism tends to optimize program development time and reliability by aiding in ability to reuse code
• However, the trade-off is that at run-time the execution is slightly slower