Outline
Other Material
We saw simple polymorphic variables in the Solitare case study.
public class Solitaire { ... static CardPile allPiles [ ]; ... public void paint(Graphics g) { for (int i = 0; i < 13; i++) allPiles[i].display(g); } ... }
The variable was declared as CardPile, but actually held a number of different types.
The most common polymorphic variable is the one that holds the receiver during the execution of a method.
Call this in C++ and Java, self in Smalltalk and Objective-C, current in Eiffel.
Holds the actual value (the dynamic class) during execution, not the static class.
The greatest power of the receiver variable comes in the development of software frameworks.
In a framework, some methods are implemented in the parent class and not overridden (called foundation method), others are defined in the parent class, but intended to be overridden (called deferred method).
Consider a class Window with subclasses TextWindow and GraphicsWindow.
The combination of foundation and deferred methods allow high level algorithms to be reused and specialized in new situations.
class Window { public void repaint () { // invoke the deferred method paint. // Because the implicit receiver, this, // is polymorphic, the method from the // child class will be executed paint (graphicsContext); } abstract public void paint (Graphics g); // deferred private Graphics graphicsContext; } class GraphicsWindow extends Window { public void paint (Graphics g) { // do the appropriate painting job } }
Only the child class knows how to paint the window. The receiver variable is responsible for remembering the actual class of the receiver when executing the method in the parent class.
In Java and Smalltalk there is another pseudo-variable, named super.
Super is like self, only when a message is given to super it looks for the method in the parent class of the current class.
class Parent { void exampleOne () { System.out.println("In parent method"); } } class Child extends Parent { void exampleOne () { System.out.println("In child method"); super.exampleOne(); } }
Variable is called base in C#.
It is sometimes necessary to undo the assignment to a polymorphic variable.
That is, to determine the variables true dynamic value, and assign it
to a variable of the appropriate type.
This process is termed down casting, or, since it is undoing the polymorphic assignment, reverse polymorphism.
Various different syntaxs are used for this, see the book.
Parent aVariable = ...; Child aCard; if (aVariable instanceof Child) aChild = (Child) aVariable;
A polymorphic method (also called pure polymorphism) occurs when a polymorphic variable is used as an argument. Different effects are formed by using different types of value.
class StringBuffer { String append (Object value) { return append(value.toString()); } ... }
Different objects implement toString differently, so the effects will vary depending upon the argument.
This example is from Smalltalk.
between: low and: high ^ (low <= self) and: [ self <= high]
Different arguments will implement the relational test differently, so different effects can be achieved.
x between: $a and: $z x between: 1 and: 100 x between: 3.14 and: 4.56 x between: "abc" and: "pdq" x between: 10@5 and: 50@40Intro OOP, Chapter 17, Slide 09
Chapter Summary