






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
An in-depth exploration of polymorphism in computer science, discussing its various forms, including pure polymorphism, overloading, and overriding. The text also covers the differences between statically and dynamically typed languages and provides examples using the Solitaire and Pinball applications. Students can use this document as study notes, summaries, or as a reference for understanding polymorphism concepts.
Typology: Summaries
1 / 11
This page cannot be seen from the preview
Don't miss anything!







The term polymorphic has Greek ro ots and means roughly \many forms." (poly = many, morphos = form. Morphos is related to the Greek go d Morphus, who could app ear to sleeping individuals in any form he wished and hence was truly p olymorphic.) In biology, a p olymorphic sp ecies is one, such as Homo Sapiens, that is characterized by the o ccurrence of di erent forms or color typ es in individual organisms or among organisms. In chemistry, a p olymorphic comp ound is one that can crystallize in at least two distinct forms, such as carb on, which can crystallize b oth as graphite and as diamond.
In ob ject-oriented languages, p olymorphism is a natural result of the is-a relationship and of the mechanisms of message passing, inheritance, and the concept of substitutability. One of the great strengths of the OOP approach is that these devices can b e combined in a variety of ways, yielding a numb er of techniques for co de sharing and reuse. Pure polymorphism o ccurs when a single function can b e applied to arguments of a variety of typ es. In pure p olymorphism, there is one function (co de b o dy) and a numb er of interpretations. The other extreme o ccurs when we have a numb er of di erent functions (co de b o dies) all denoted by the same name{a situation known as overloading or sometimes ad hoc polymorphism. Between these two extremes are overriding and deferred methods.^1
(^1) Note that there is little agreement regarding terminology in the programming language commu- nity. In [Horowitz 1984 ], [Marcotty 1987 ], [MacLennan 1987 ], and [Pinson 1988 ] for example, polymor- phism is de ned in a manner roughly equivalent to what we are here calling overloading. In [Sethi 1989 ] and [Meyer 1988a ] and in the functional programming languages community (such as [Wikstrom 1987 , Milner 1990 ]), the term is reserved for what we are calling pure polymorphism. Other authors use the term for one, two, or all of the mechanisms describ ed in this chapter. Two complete, but technically daunting, analyses are [Cardelli 1985 ] and [Danforth 1988 ].
With the exception of overloading, p olymorphism in ob ject-oriented languages is made p os- sible only by the existence of polymorphic variables and the idea of substitutability. A p olymorphic variable is one with many faces; that is, it can hold values of di erent typ es. Polymorphic variables emb o dy the principle of substitutability. In other words, while there is an exp ected typ e for any variable the actual typ e can b e from any value that is a subtyp e of the exp ected typ e. In dynamically b ound languages (such as Smalltalk), all variables are p otentially p olymorphic{ any variable can hold values of any typ e. In these languages the desired typ e is de ned by a set of exp ected b ehaviors. For example, an algorithm may make use of an array value, exp ecting the subscripting op erations to b e de ned for a certain variable; any typ e that de nes the appropriate b ehavior is suitable. Thus, the user could de ne his or her own typ e of array (for example, a sparse array) and, if the array op erations were implemented using the same names, use this new typ e with an existing algorithm. In statically typ ed languages, such as Java, the situation is slightly more complex. Poly- morphism o ccurs in Java through the di erence b etween the declared (static) class of a variable and the actual (dynamic) class of the value the variable contains. A go o d example of a p olymorphic variable is the array allPiles in the Solitare game presented in Chapter 9. The array was declared as maintaining a value of typ e CardPile, but in fact it maintains values from each of the di erent sub classes of the parent class. A message presented to a value from this array, such as display in the example co de shown b elow, executes the metho d asso ciated with the dynamic typ e of the variable and not that of the static class.
public class Solitaire extends Applet f ... static CardPile allPiles [ ]; ...
public void paint(Graphics g) f for (int i = 0; i < 13; i++) allPiles[i].display(g); g ... g
We say a function name is overloaded if there are two or more function b o dies asso ciated with it. Note that overloading is a necessary part of overriding, which we and will describ e
There may b e four di erent functions, corresp onding to integer + integer, integer + real, real + integer, and real + real. In this case, there is overloading but no co ercion.
There may b e two di erent functions for integer + integer and real + real. In integer
There may b e only one function, for real + real addition. All arguments are co erced into b eing real. In this case there is co ercion only, with no overloading.
There are two di erent forms of overloading that can b e distinguished. One form o ccurs when the same function name is found in two or more classes that are not linked by inher- itance. A second form o ccurs when two or more functions with the same name are found within one class de nition. The latter form will b e describ ed in the next section. A go o d example of overloading of the rst typ e is the metho d isEmpty. This metho d is used to determine if an ob ject is empty, however the exact meaning of empty will di er dep ending up on circumstances. The message is understo o d by the classes Vector, Hashtable and Rectangle. The rst two are collection classes, and the message returns true when there are no elements in the collection. In the class Rectangle the message returns true if either the height or width of a rectangle is zero, and thus the rectangle has no area.
Rectangle r1 = new Rectangle (); if (r1.isEmpty()) ...
Overloading Do es Not Imply Similarity
There is nothing intrinsic to overloading that requires the functions asso ciated with an overloaded name to have any semantic similarity. Consider a program that plays a card game, such as the solitaire game we examined in Chapter 9. The metho d draw was used to draw the image of a card on the screen. In another application we might also have included a draw metho d for the pack of cards, that is, to draw a single card from the top of the deck. This draw metho d is not even remotely similar in semantics to the draw metho d for the single card, and yet they share the same name. Note that this overloading of a single name with indep endent and unrelated meanings should not necessarily b e considered bad style, and generally it will not contribute to con- fusion. In fact, the selection of short, clear, and meaningful names such as add, draw, and so on, contributes to ease of understanding and correct use of ob ject-oriented comp onents. It is far simpler to rememb er that you can add an element to a set than to recall that to do so requires invoking the addNewElement metho d, or, worse, that it requires calling the routine Set Mo dule Addition Metho d.
All ob ject-oriented languages p ermit the o ccurrence of metho ds with similar names in unrelated classes. In this case the resolution of overloaded names is determined by obser- vation of the class of the receiver for the message. Nevertheless, this do es not mean that functions or metho ds can b e written that take arbitrary arguments. The statically typ ed nature of Java still requires sp eci c declarations of all names.
Another style of overloading, in which pro cedures (or functions or metho ds) in the same context are allowed to share a name and are disambiguated by the numb er and typ e of arguments supplied, is called parameteric overloading; it o ccurs in Java as well as in some imp erative languages (such as Ada) and many functional languages. Parameteric overload- ing is most often found in constructor functions. A new Rectangle, for example, can b e created either with no arguments (generating a rectangle with size zero and northwest cor- ner 0,0), with two integer arguments (a width and height), with four integer arguments (width, height, northwest corner), with a Point (the northwest corner, size is zero), with a Dimension (height and width, corner 0,0), or with b oth a Point and a Dimension.
Rectangle r1 = new Rectangle (); Rectangle r2 = new Rectangle (6, 7); Rectangle r3 = new Rectangle (10, 10, 6, 7); Point p1 = new Point (10, 10); Dimension d1 = new Dimension (6, 7); Rectangle r4 = new Rectangle (p1); Rectangle r5 = new Rectangle (d1); Rectangle r6 = new Rectangle (p1, d1);
There are six di erent constructor functions in this class, all with the same name. The compiler decides which function to execute based on the numb er and typ e of arguments used with the function call. Overloading is a necessary prerequisite to the other forms of p olymorphism we will consider: overriding, deferred metho ds, and pure p olymorphism. It is also often useful in reducing the \conceptual space," that is, in reducing the amount of information that the programmer must rememb er. Often, this reduction in programmer-memory space is just as signi cant as the reduction in computer-memory space p ermitted by co de sharing.
In Chapter 8 we describ ed the mechanics of overriding, so it is not necessary to rep eat that discussion here. Recall, however, the following essential elements of the technique. In one class (typically an abstract sup erclass), there is a general metho d de ned for a particular
addCard(new Card(i, j));
// then shue the cards Random generator = new Random(); for (int i = 0; i < 52; i++) f int j = Math.abs(generator.nextInt()) % 52; // swap the two card values Object temp = thePile.elementAt(i); thePile.setElementAt(thePile.elementAt(j), i); thePile.setElementAt(temp, j); g g
g
When used in this fashion, the call on the parent constructor must b e the rst statement executed. If no call on sup er is make explicitly and there exist two or more overloaded forms of the constructor, the constructor with no arguments (sometimes called the default constructor) will b e the form used.
A metho d that is declared as abstract can b e thought of as de ning a metho d that is deferred; it is sp eci ed in the parent class but must b e implemented in the child class. Interfaces can also b e viewed as a metho d for de ning deferred classes. Both can b e considered to b e a generalization of overriding. In b oth cases, the b ehavior describ ed in a parent class is mo di ed by the child class. In an abstract metho d, however, the b ehavior in the parent class is essentially null, a place holder, and al l useful activity is de ned as part of the co de provided by the child class. One advantage of abstract metho ds is conceptual, in that their use allows the program- mer to think of an activity as asso ciated with an abstraction at a higher level than may actually b e the case. For example, in a collection of classes representing geometric shap es, we can de ne a metho d to draw the shap e in each of the sub classes Circle, Square, and Triangle. We could have de ned a similar metho d in the parent class Shap e, but such a metho d cannot, in actuality, pro duce any useful b ehavior since the class Shap e do es not have sucient information to draw the shap e in question. Nevertheless, the mere presence of this metho d p ermits the user to asso ciate the concept draw with the single class Shap e, and not with the three separate concepts Square, Triangle, and Circle. There is a second, more practical reason for using abstract metho ds. In statically typ ed ob ject-oriented languages, such as Java, a programmer is p ermitted to send a message to an ob ject only if the compiler can determine that there is in fact a corresp onding metho d
that matches the message selector. Supp ose the programmer wishes to de ne a p olymorphic variable of class Shap e that will, at various times, contain instances of each of the di erent shap es. Such an assignment is p ossible, according to our rule of substitutability; neverthe- less, the compiler will p ermit the message draw to b e used with this variable only if it can ensure that the message will b e understo o d by any value that may b e asso ciated with the variable. Assigning a metho d to the class Shap e e ectively provides this assurance, even when the metho d in class Shap e is never actually executed.
Many authors reserve the term polymorphism (or pure polymorphism) for situations where one function can b e used with a variety of arguments, and the term overloading for situ- ations where there are multiple functions all de ned with a single name.^2 Such facilities are not restricted to ob ject-oriented languages. In Lisp or ML, for example, it is easy to write functions that manipulate lists of arbitrary elements; such functions are p olymorphic, b ecause the typ e of the argument is not known at the time the function is de ned. The abil- ity to form p olymorphic functions is one of the most p owerful techniques in ob ject-oriented programming. It p ermits co de to b e written once, at a high level of abstraction, and to b e tailored as necessary to t a variety of situations. Usually, the programmer accomplishes this tailoring by sending further messages to the receiver for the metho d. These subsequent messages often are not asso ciated with the class at the level of the p olymorphic metho d, but rather are deferred metho ds de ned in the lower classes. An example will help us to illustrate this concept. As we noted in Chapter 8, the class Numb er is an abstract class, parent to the wrapp er classes such as Integer, Double, Float. The de nition of the class is similar to the following:
public abstract class Number f
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
(^2) The extreme cases may b e easy to recognize, but discovering the line that separates overloading from p olymorphism can b e dicult. In b oth Java and ML a programmer can de ne a numb er of functions, each having the same name, but which take di erent arguments. Is it overloading in Java b ecause the various functions sharing the same name are not de ned in one lo cation, whereas in ML-style p olymorphism they must all b e bundled together under a single heading?
Other forms of p olymorphism include overloading from indep endent classes, parameteric overloading (overloading that is disambiguated by the typ es of arguments used in a function call), and abstract metho ds. Note that the use of p olymorphism tends to optimize program development time and reliability, at the cost of run-time eciency. For most programs, the b ene ts far exceed the costs.
In the interests of completeness, it should b e mentioned that there is at least one imp ortant style of p olymorphism, found in other computer languages, that is not found in Java. A generic (sometimes called a template) is a technique that allows a class description to b e parameterized with a typ e. In C++, for example, one could declare a class as follows:
template
The result is a \b ox of T", and not simply a b ox. To create such a value, one must also sp ecify a typ e for the parameter value T:
box
One imp ortant place where this mechanism is useful is in the creation of collection classes (see Chapter 19). A language with generics, for example, would allow one to declare a vector of Cards, rather than (as in Java) simply a vector of ob jects. The compiler can then verify that the collection contains only the indicated typ e of values. More imp ortantly, the compiler can avoid the cast necessary in Java when an ob ject is removed from a container A discussion of generics in relation to other forms of p olymorphism can b e found in [Budd 97 ].