{3/25/05: Incorporate "polymorphism and casting" from JavaWorld article.}
INCORPORATE GENERICS WHEN ALL STUDENTS HAVE JAVA BACKGROUNE.
{Add: pure polymorphism requires dynamic binding => ad hoc doesn't () => pure occurs at run time & ad hoc occurs at compile time.)
{Incorporate, explicitly, the OOPL facilities that implement the various semantic concepts of polymorphism in an abstract model of a real world system.}
warning_.gifupdated.gifModified 5/12/02; 5/28/03; 4/27/04; 4/27/06warning_.gif
This Learning Module is currently under reconstruction!
The following is a conversion of  my handout in COSC 390 OOSD IN C++, from Fall, 1995 to an equivalent for Java.

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.
 

  •     The goals of this learning module are:
    1. to illustrate the concept of polymorphism from a language independent viewpoint.
    2. to distinguish, in concept and functionality, the various forms of polymorphism from a language independent viewpoint.
    3. to analyze, in a memorable form, how polymorphism is implemented in Java, e.g.
      1. what forms of polymorphism are (and are not) currently avaiable in Java and
      2. how Java implements its available forms
    4. to emphasize the differences between the implementations of polymorphism in Java and C++.
    5. to help the student to learn how to incorporate polymorphism in Java architectures (programs).
    The sequence of presentations, in this Learning Module, is:
    1. POLYMORPHISM IN GENERAL
      1. Generic Categories of Polymorphism
      2. 1.2 General Properties of Polymorphism
    2. AD HOC POLYMORPHISM IN JAVA
      1. Ad Hoc Polymorphism via Conversion/Coercion
      2. Ad Hoc Polymorphism via Method (or Constructor) Overloading
    3. PURE POLYMORPHISM IN JAVA
    4. SUMMARY {NEEDS TO BE WRITTEN}
    1. POLYMORPHISM IN GENERAL:

        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. Ad Hoc Ploymorphism results in code; therefore, it occurs at compile time.  It is manifested in coercion/conversion and when multiple method definitions have the same name, but different signatures.
      1. Coercion is necessary because an arithmetic expression can have different resultant types, depending on the types of its variables. Coercion ( _______(3a) conversion) is the automatic conversion between built-in-types carried out by the compiler, when the types of two values of a binary operation are not identical, for example, when an integer attribute is added to a float attribute, the result has a type ________(3b).
        1.  
          x + y // the type of this result is determined by built-in coercions in virtually all languages
           
      2. Conversion is an explicit change specified by the code itself. This is accomplished, in Java and C++, via a cast, uninary opertion that converts one type to another, e.g. if I is of type int,
        1.  
          int i= (int)12.5f; // the cast form, in Java, of explicit conversion from integer to float
        (Another form in C++ is the use of functions, e.g.
         
          f = float(i); // the C++ functional form of explicit conversion from integer to float)
           
      1. Overriding (See section section 4.2.B of LM VI.) inherited instance methods was covered in LM VI, so only the essential features are reviewed here.  Overriding occurs when an inherited method is redefined, or, augments the superclass method.  (Note that "overriding" is sometimes called "overwriting".)  There are two forms of overriding:
        1. Replacement occurs when the code of the inherited method is not executed at all, i.e. it is completely superceded by the code in the overriding method.
        2. Refinement augments an inherited method by combines the code of the inherited method, via an explicit invocation, with newly defined code.  This is accomplished by calling, from within the overriding method, a superclass method using the keyword super or explicitly calling an ancestor method with its fully qualified name (dot notation); thus the inherited code is executed in the context of the subclass code.
      2. Hiding (See section 4.2.C of LM VI.)  inherited class methods and attributes (fields) has the same effect as overriding inherited instance methods, i.e. the subclass definitions and declarations supersede those with the same name and signature in ancestor classes.  (Note that hiding is called "shadowing" in Java In A Nutshell.)
      3. Overloading (See section 4.2.D of LM VI.) is the use of the same name for different constructors/methods ("method overloading") or same symbol for different operators ("operator overloading" which is available in C++ but not Java).  These common names or symbols may be in the same class or different classes.  Overloaded constructors or methods can be distinguished by their "___________(4)" (defined as the list of argument types in its parameter list). For example, ad hoc polymorphism via constructor overloading would be:
        1.  
          Point() {x =0; y=0};
          Point(int x, int y) {this.x =x; this.y =y};
           
      4. Abstract methods are "declared" in a parent class but "defined" in derived classes, i.e. the declaration is a "template" that must be explictly defined in a subclass.  Such methods are facilitated by combining dynamic binding with subtyping.  Inheritance used as _____________(5) makes it possible for a class be a "subtype" of an ancestor. Methods available for the ancestor, if not ____________(6) will work on the subtype. Such a method can have different implementations (different versions found within different classes) that are invoked by a run-time determination of subtype (choice of class), e.g. _________(7) in the TwoDShapes package implemented in our labs.
    SAQ 1: What is the (a) similarity and (b) difference between overriding, hiding, and overloading?
    1. Pure Polymorphism , becauses it utilizes dynamic binding, occurs at run time It has three forms:
      1. Polymorphic attributes are made possible by combining dynamic binding and the principle of substitutability (i.e. inheritance used as ___________(8)).  A polymorphic attribute is one whose associated variable can be of various types (classes).  Although there is an expected type for any variable, the actual type can be from any type that is a subclass of the expected type().
      2. Polymorphic methods are also facilitated by dynamic binding. They occurs when a single method can be applied to arguments of a variety of types (classes). Usually the definition of such a method will make use of other forms of polymorphism.  The simplest case of polymorphic methods is, as with polymorphic attributes, a consequence of the principle of substitutability, i.e. a method can be used by any instance whose type is a subclass of the expected type().
      1. Parametric classes (called "generics" in Java 1.5 and "templates" in C++) facilitate generic class defintions which facilitates the abstraction of data types The type (class) of an ADT (abstract data type) definition is left unspecified and is later instantiated by a message according to the current state of the runtime environment of the program. Parametric classes were  not implemented in Java until Java 1.5, which is NOT currently part of COSC 390{INCORPORATE WHEN ALL STUDENTS HAVE JAVA BACKGROUNE}.   In general, generics allow Java developers to define a single class, for example Stack, that can be instantiated with different types, e.g.
    Stack<Integer> s1 = new Stack<Integer>(); //instantiates a stack of integer type
    Stack<Float> s2 = new Stack<Float>(); //instantiates a stack of float type
    Stack<Square> s3 = new Stack<Square>; //instantiates a stack of instances of the class square
    Note that manipulation of generic pointers and templates provide polymorphic classes in C++.  This allows C++ developers to define templates; for an equilivant example Stack see section 3.2 of POLYMORPHISM IN C++.

    SAQ 2: There are numerous SAQs (perhaps they are TPQs at this stage) that can be asked here. Do so; then answer them. (Hint: remember the ol’ W. I. T. D/S. B.) Which are the most important questions, i.e. ones that would qualify for the QUALIFYING EXAM?

    1.2 General Properties of Polymorphism:

    1. The categories of method polymorphism can be distinguished by the number of available methods or "when" it occurs.  
      1. Pure polymorphism occurs, at run time, when a single method accepts arguments with a variety of types.  This requires dynamic binding, a facility characteristic of OOPL.
      2. Ad hoc polymorphism occurs in source code, i.e. at compile time, when there are several different methods (different definitions, i.e. different code bodies) that have the same name.
    2. The polymorphic variable, a key concept in polymorphism, can hold values of different types. They embody the principle of substitutability in that, although there is an expected type for any variable (that of the attribute declaration), the actual type can be from any value that is a subtype of the declared type.
    3. Pure polymorphism can only be implemented in languages, like Java, that support dynamic binding (sometimes called late binding). Dynamic binding associates program identifiers with specific memory locations (a message with a particular method) at run time. It permits each class of a package to have different implementation with the same method name. Client programs can apply the method to an instance of one of the classes without regard for the specific class of the instance. At run time Java determines the class of the instance and sends the message to that class.
      1. A primary objective of dynamic binding is to make it possible for software architectures to be more easily extended during both development and maintenanceThis is more easily accopmlished using dynamic binding because, such architectures can be designed to perform operations on generic objects, e.g. the "shapes" of our the twoDShapes package of our labsThese operations are generic because they can be used with objects of any subclass of the same ancestor class, e.g. the circles, triangles, etc. (subclasses of TwoDimShape) of our the twoDShapes package of our labs Extendability is facilitated because new shapes, e.g. pentagons, can be added as subclasses of TwoDimShape and inherit all the capabilitities their superclass and will be treated simply as another type of shape, automatically, being include in all operations on generic shapes.
    4. It is important to understand the distinction between dynamic binding and dynamic typing.
      1. Dynamically typed languages (like Smalltalk, Lisp, Logo, etc.) are untyped and thus are essentially polymorphic.  In such languages, all variables are potentially polymorphic, i.e. any variable can hold values of any type.  In thse languages the desired type is defined by a set of expected behaviors, e.g. arrays have index access to elements, but the elements themselves can have various types.
      2. Statically typed languages (like Java, C++, and most procedural languages) have types declared at compile time.  Thus polymorphism in statically typed languages is more complicated than in dynamically typed languages.  If a statically typed language is polymorphic, instance variables can have different types at run time, because, during program execution, an instance can have the type of any ancestor in the inheritance hierarchy. The essential idea is that there is a difference between the declared (static) class of an attribute and the actual (dynamic) class of the variable.
    5. Polymorphism localizes responsibility for behavior, thus minimizing side effects. This is a distinct advantage because client code frequently requires no revision when improved functionality is added to the system through manufacturer-provided code updates.  Polymorphism helps to insure that such revisions do not have unexpected effects in clients.
    6. Polymorphism augments _________________(9) via the "black box principle"
      1. The virtual methods specified in a base class are the interface that guides the developer when defining those methods in classes where they are inherited. The developer knows that an overriding method completely defines the behavior of the class in which it is defined, and can prevent the user from seeing its inner workings; such a method appears to be a "black box" that receives input and produces the required output.
      2. On the other hand, developers does not need to know the details of the methods, in other classes, that they use in the construction of an application. The users of a class sees it as a black box; they develop software that provides input to that black box and makes use of its output without knowing how that output was produced.
      These facilitate true modular software development via reuse of proven components (black boxes).
    7. In OOP, polymorphism is integrated with information hiding, and inheritance; they all work together to facilitate a more powerful software development paradigm than structured programming. Thus, although we consider them seperately, we must remember the are synergystic parts of a whole:
      1. ____________(10) assures that client programs interact with instances only by sending messages to methods that govern the behaviour of the object.
      2. ___________(11) provides a means for expressing the differences among classes, while facilitating reuse of attributes and methods that implement similar features.
      3. _____________(12) helps to make client programs more general by hiding the differences among classes, expressed via inheritance, from the client programs. Java makes the choice of what method to call at the time of the call.
    8. One principle of OOPL is that developer-defined types (classes) must enjoy the same privileges as built-in types. Developers expect the convenience of using their types without regard to a native/developer-defined distinction. The ability of a language to achieve this result is the test of its adequacy for OOP use. Built-in types (like should be able to be mixed with user-defined types because it is convenient and would otherwise be burdensome to designate conventionally expected conversions.
    SAQ 3:

    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:

    1. Conversion and coercion, covered in Java Basics and summmarized in section 1.1.A, above, are primative forms of polymorphism and often not even referred to as polymorphic properties of a language.
    2. One important goal of Java, like C++, was the identical treatment of all types and classes.  This requires the integration of primitive types, classes and interfaces of the Core Java API, and user-defined classes, so that there is no distinction between how the compiler handles them and consequently they can be freely mixed.
    3. All casts in Java ar type safe, i.e. Java casts are roughly equivalent to dynamic_cast of references in C++.  This means that an improper cast results in an exception being thrown.  These exceptions are too numerous and tedious to be discussed here; suffice it to say that they reflect common sense.  For a complete explanation of casting and the larger subject of type conversions, see Chapter V, Conversions and Promotions of The Java Language Specification, by Gosling, Joy and Steele.
    2.2 Ad Hoc Polymorphism via Method (or Constructor) Overloading:

            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.)

    1. In general, overloading occurs in all programming languages.  This usually appears when different functions, procedures, or operators are used to provide semantically similar actions for different data types, e.g. the "+" operator may be used with integers and real numbers and often is the concatenation operator for strings.
    2. In OOPL, overloaded methods are a by-product of using classes. The class provides a built-in information hiding mechanism that associates names to the class where they are declared or to its subclasses.  Therefore, the developer is free to choose any name within a class although one must always be aware that reusing names used in ancestor classes causes overriding, hiding, as well as overloading.
    3. There are two different forms of overloading:
      1. Normal overloading occurs whe the same method name is found in classes that are not related by inheritance.  All OOPL permit identical method names in unrelated classes.  In such cases the resolution of overloaded names is determined by observation of the class of the message receiver.  Nevertheless, this does not mean that methods can be written that take arbitrary arguments.  The statically typed nature of java still requires specific declarations of all names.  (Note: I call the "normal" overloading simply to give it a distinct name; "normal" is not standard name.  (There does not seem to be one!))
      2. Parametric overloading occurs when methods with the same name are used within the same class or ancestor classes.  For example, assume a method adds integers, floating point numbers, as well as concatenates strings. A single method name "add" may be used for all three versions. Each is a separate version of add, distinguishable by its "_____________"(13) (characteristic argument types), e.g.
        1.  
          public int add(int n1, int n2){...}
          public float add(float n1, float n2){...}
          public String add(String c1, String, c2){...}

        When a message add is encountered, the Java compiler uses the data types in the argument list to call the correct version of the method add.  Of course using "add" as an example is redundant, but it illustrates overloading especially when we note that, in Java, add() is already overloaded, appearing in numerous classes such as Component, Container, List, Rectangle, etc.  (See the Class, Method, and Field Index of Java In a Nutshell.)
    4. Overloaded methods are invoked by a type-matching algorithm for arguments that includes having the implicit argument matched to an instance of that class type. In a strongly typed language, like Java, the compiler can often determine the correct method at compile time and can therefore generate only a single code sequence thus optimizing performance.
    5. Note that if  two classes are related via inheritance, overloading can become ____________(14).
    6. Advantages of function overloading: Overloading saves development time and effort and allows the developer to use a natural syntax that suits the system being modelled.  For example, in a langauge not providing overloading, the functions circleArea, squareArea, and triangleArea  may be defined to return the areas of a circle, square, and triangle respectively. Assuming that each may be used with integer or float parameters, two versions of each would be required, thus the programmer has to become familiar with six functions for calculating area.
      1. Java saves time and effort in defining identifier names: In Java a single overloaded method name, area, may be defined. Six methods must be defined (This could be reduced, in C++ but not Java, to three with parametric polymorphism or "templates".), but they all have the same meaningful name representing the concept of area. The method provide all the information needed for the compiler to determine is appropriate usage. Thus the Java programmer expends less effort defining and remembering numerous distinct names and more time developing the application.
      2. Java allows meaningful identifier names to be used, with minimal restrictions.The names can be chosen to naturally represent the system being modelled instead of worrying about confusing the compiler.  This natural syntax not only  makes utilizing an OO application easier by the casual user but also makes maitainence and modification easier by programmers were not involved in the original development.The same name for an identifier can be used over and over as long as (1) the ____________________(15)are different or (2) the ___________(16a) to which the method belongs are different and not related by ___________(16b).
    7. It is important to note that, in general, overloading is a necessary prerequisite to other forms of polymorphism (overriding, abstract methods, and pure polymorphism).
    8. Unlike other forms of polymorphic methods, overloaded methods are not necessarily associated with inheritance.
    SAQ 4: (a)If the same method name is used in two classes related via inheritance, when is this overloading.  (b) What else can it be?
    SAQ 5: (a) Does the signature of identically-named methods belonging to two different classes have to be different? (b) Does the class of identically-named methods have to be different? Explain.

    2.3 Ad Hoc Polymorphism via Operator Overloading is not Implemented in Java:

    2.4 Ad Hoc Polymorphism via Hiding and Overriding:

    1. Both hiding and Overriding are consequences of overloading combined with inheritance.
    2. Both were covered in LM VI on Inheritance.
    SAQ 6: Explain how hiding and overriding are consequences of overloading and inheritance.

    2.5 Ad Hoc Polymorphism via Abstract/Deferred Methods:

    1. An abstract method can be viewed as one whose definition is deferred.  It is specified in the declaration in an ancestor class and must be _________(17) in a decendent class in order for that class to be instantiated.
      1. An abstract class has ________________(18) abstract method and _____________________________(19).
      2. An interface has _______________________________________(20).
      Both can be considered a generalization of __________________(21) because the behavior declared in the ancestor class must be modified in the decendent, otherwise that class will be _____________(22).
    2. Since abstract methods are inherently associated with inheritance, they were covered in section 5 (abstract classes) and section 6 (interfaces) of LM VI.
    3. Interfaces are a polymorphic construct because, by definition, all of their methods are abstract and therefore must be defined in any class that implements an interface.  Their concepts presupposes that there will be multiple classes that implement an interface; therefore, all the declared methods of an interface are designed for polymorphism.
    SAQ 7:

    3. PURE POLYMORPHISM :

            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:

    1. A polymorphic attribute is one whose associated variable can be of various types (classes).  In other words when an instance of a class containing a polymorphic attribute is accessed the variable associated with that polymorphic attribute can have different types (any of the subtypes) during the execution of the program.
      1. The developer can define polymorphic variables of the type of the parent class that are also able to reference instances of any of the subclasses of that class.
      2. A method defined in an ancestor class can be overriden in a decendent class.  The behavior of the overriding methods are similar, but must be customized for the class to which it belongs. (Note that the principle of substitutability convention says that the decendent class should not be restricted or limited form of the superclass.  This is the origin of the square is-a rectangle controversy!)   When such a method is invoked through the polymorphic variable, the associated message is bound, dynamically, to the method in the correct class.
    2. In statically typed languages like Java and C++ there is an decared type for any variable defined at compile time; however because of the ______________________(23), the actual type, during execution, can be of any type that is a subclass of the declared type.  This form of pure polymorphism occurs through the difference between the declared (static) class of an attribute and the variety of actual (dynamic) classes that can be assocated with of the instance variable.
    3. For example in our twoDShapes package of our labs, we can declare a method draw in the class Polygon even though it is impossible to draw an "arbitrary" polygon.  The presence of this method helps the user to associate the operation of drawing to a single class (Polygon) instead of with the various subclasses (Circle, Triangle, Rectangle, etc.) each of which has its unique draw method that overrides the draw method in Polygon.  Therefore, we can define a polymorphic attribute to be of type Polygon that can, at various times, contain instances of each of the different shapes.    The Java compiler will permit the message draw to be used with this variable only if it can ensure that the message will be understood by any subclass instance that may be associated with the variable.  Assigning the method draw to the class Polygon effectively provides this assurance, even when the draw in the class Polygon is never actually executed.
    SAQ 8: (a) Using the twoDShapes package of our labs, illustrate polymorphic attributes using a method addShape which adds an instance of any shape to a collection of shapes?  (b) What is the easiest (almost "trivial") way to incorporate polymorphism into a method?  (HINT: consider the type declaration of its parameters.)

    3.2 Polymorphic Methods in Java:

    1. The ability to form polymorphic methods is one of the most powerful techniques in OOSD.  It permits code to be written once, at a high level of abstraction, and then to be modified as necessary to fit a variety of situations.
    2. A polymorphic method allows the selection, at run-time, of the appropriate method from identically named methods among superclasses and subclasses; in Java, this can be accomplishe using the language's built-in dynamic binding. (In C++, ploymorphic methods are called "virtual methods" and are implemented by a rather complicated pointer mechanism. In Java all methods are handled consistently, and are dynamically bound, except for methods that are defined with the final modifier.  This is another example of the simplicity of Java when compared to C++.)
      1. The defining characteristic of polymorphic methods (as opposed to overloading) is that there is one method with the given name used with a variety of different arguments.
      2. Usually the body of a polymorphic method will include other forms of polymorphism, e.g. the invocation of an abstract method intValue() by the polymorphic method byteValue() the following example (the core Java Library class Number, parent of the wrapper classes such as Integer, Double, Float, etc).
        1.  
          public abstract class Number { // an abstract class whose definition is deferred
            public abstract int intValue(); // an abstract method whose definition is deferred
            public abstract long longValue(); // ditto
            public abstract float floatValue(); // ditto
            public abstract double doubleValue(); // ditto
            public byte byteValue()//a purely polymorphic method that should not be overridden
                {return (byte) intValue();}
            public short // ditto
                {return (short) intValue();}
          }//end class Number

        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).

    SAQ 9: (a) Could Number, in the preceding example be implemented as an interface?  Explain.  (b) Are the methods draw and addShape, in the preceding section (on polymorphic attributes), polymorphic methods?  Justify your answer.

    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.)

    1. The parametric class construct (also called "generics" or "templates"), which facilitate generic class declarations, has been incorporated in Java 1.5 (JavaTM 2 Platform Standard Edition version 5.0).  This long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting.
      1. After considerable debate, parametric classes, was not implemented in the original versions of Java. Apparently, this decision was based on the overriding desire to keep Java as simple as possible by avoiding facilities that are not often used.
    2. Essentially generics facilitates the abstraction of types, i.e. operations/methods can be defined independently of the types on which they operate.
    3. To see how templates are implemented in C++, see section 3.2 of POLYMORPHISM IN C++.
    4. SUMMARY: