LEARNING MODULE VII
POLYMORPHISM IN JAVA
Polymorphism, in OOSD, allows the software developer to reuse names as well as code, thus making software development, as well as its maintenance and use, more natural to humans. In fact, polymorphism has been called the "Genie in OOP" that accepts the "wishes" of a client, properly interprets them, and responds to them according the current state of the runtime system, all without bothering the user. Polymporphism is a natural consequece of specialization (subclassing relationship implemented via inheritance), the associated principle of substitutability, and message passing. In fact, one of the most powerful features of polymorphism is that these facilities can be combined in a variey of ways, yielding a number of techniques for code sharing and reuse. OOSD reaches its most potent form when polymorphism complements inheritance. The combination of dynamic binding and public inheritance is the most general and flexible way to construct software.
Because polymorphism is essential to OT, it is found in all OOPL; however, the number of polymorphic facilities as well as their implementation vary greatly between languages! In Java, polymorphism is integrated throughout the language because all Java identifiers are dynamically bound and are potentially polymorphic. (This is NOT true in C++!) This makes polymorphism a natural part of the Java language that makes it unnecesary for the developer to think about using polymorphism. In fact, neither of our references (The Java Tutorial and Java In a Nutshell) even use the word "polymorphism" despite the fact that Java has intrinsic polymorphic facilities; this, unfortunately, is characteristic of texts that teach "programming in Java" instead of "OOSD using Java"! The various implementations of polymorphism in Java (coercion/conversion, overriding, hiding, overloading, abstract methods, and polymorphic attributes, and polymorphic methods) simply become tools" in a developers toolkit. However, to understand polymorphism as a concept, one should compare the implementations of polymorphism is several languages; in the following presentation (as usual), we will compare Java's implementation with that in C++. (See Polymorphism in C++, from my companion course COSC 390, OOSD IN C++.)
Unfortunately there seems to be little agreement as to the exact meaning of polymorphism in Java, much less in OOP in general. Everyone agrees that "poly" means "many" and "morphism" means "forms", so polymorphism must mean having many forms, however, from this point there is considerable divergence. The Computer Desktop Encyclopedia defines polymorphism as: "meaning many shapes. In object-oriented programming, the ability of a generalized request (message) to produce different results based on the object that it is sent to." In other words, polymorphic methods provide a means of giving different _____________(1a) to the same _____________(1b). However, this implies that only methods can be polymorphic, but an attribute name that is used in different classes (different contexts) is polymorphic, and the polymorphic variables of associated instances are a fundamental concept in polymorphism. Cardelli, Luca, and Wegner ("On Understnding Types, Data Abstraction, and Polymorphism.", Computing surveys. 17: 471-522, 1985.) distinguish four categoriess of polymorphism based on two distinct categories: Ad_Hoc Polymorphism (static binding; compile-time association between message and method) and Pure Ploymorphism (dynamic binding; run-time association between message and method). This analysis is the basis of this learning module; the four categories are previewed below and covered in detail in the subsequent sections.
If
you are an independent learner (not enrolled in the current class
COSC390
at FSU), then, before proceeding, consult the
study
guide for this module.
Polymorphism is not unique to OOP; in fact, untyped languages like Lisp and Logo are inherently polymorphic because their functions can be applied to a variey of types. This is possible because in such languages types are selected dynamically at run time; in Java and C++ types are initially specified at compile time although with dynamic binding the actual association of an instance with its type or method with its definition can occur at run time. In either case, polymorphism is an essential feature of any OOPL and, when paired with inheritance, give OOPL a unique power for the reuse of code in a way that is natural to the system being modelled.
1.1 Generic Categories of Polymorphism:
Cardelli, Luca, and Wegner separated polymorphism into two categories, "ad hoc" and "pure", long before Java was introducted. Unfortunately, there is still confusion and disagreement on the meanings of these two categories expecially when applied to implementations in different kinds of languages. The following is based on the analysis of Timothy Budd's Understanding Object-Oriented Programming with Java. He distinguishes "ad hoc polymorphism" as meaning more than one method body having the same name while "pure polymorphism" is reserved for a single method that can be used with a variety of different arguments.
1.2 General Properties of Polymorphism:
2. AD HOC POLYMORPHISM IN JAVA:
Ad Hoc polymorphism is the most common form of polymorphism used in Java. It is manifested in conversion and coercion, overloading, hiding, overriding, and abstract methods, the last three also involving inheritance.
2.1 Ad Hoc Polymorphism via Conversion/Coercion:
In overloading, it is the method or constructor name that is polymorphic. ( For practical purposes, as far as overloading is concerned, there is no distinction between methods and constructors, so in the following, only the word "method" is used.) A method name is overloaded if two or more method bodies are associated with it. Such an overloaded method can be viewed as a single "abstract" method that takes various types of arguments; the actual code executed depends on the arguments given. (See the discussion in section 4.2.D of LM VI which emphasizes the dependence of overloading on inheritance.)
2.3 Ad Hoc Polymorphism via Operator Overloading is not Implemented in Java:
2.4 Ad Hoc Polymorphism via Hiding and Overriding:
2.5 Ad Hoc Polymorphism via Abstract/Deferred Methods:
Pure polymorphism was not as frequently apparent
overtly in Java, as in some other OOSDL (e.g. C++), because (1) the
ubiqueteous
dynamic binding makes other uses essentially transparent, and (2)
parametric
classes (templates), which are essentially polymorphic, were not
implemented in Sun's Java until Java 1.5.
Parametric classes,
called "generic types",
are implemented in Java 1.5; see the overview of Java 1.5 in J2SE 1.5 in a
Nutshell. (You will have to scroll down to find the
section "Generic Types".) This is
not true in C++ where dynamic binding is explicitly defined only for
virtual
methods; these are inherently associated with C++ pointers and are,
therefore,
complicated. This complication is removed by Java's built-in
dynamic
binding.
3.1 Polymorphic Attributes in Java:
3.2 Polymorphic Methods in Java:
The method byteValue()is purely polymorphic because regardless of whether the receiver of that message (a subtype of Number, e.g. a complex number) has a type integer, long, float, or double, the preceding definition is the only one used; on the other hand, the abstract method intValue() displays _______(24) polymorphism because it will have numerous definitions (possibly a different definition in each subtype of Number).
3.3 Parametric Classes (Templates
in C++) Have Been Implemented in Java 1.5 as "Generics":
For an
Introduction to Generics see the Generics
Trail in the Java Tutorial.
(You are responsible only for the Introduction
to the Generics Trail.)