200 likes | 220 Views
Explore polymorphism in OOP - from forms in biology to code in C++. Learn about polymorphic variables, functional polymorphism, and overloading. Understand how polymorphism enhances code flexibility and functionality.
E N D
CSCI-383 Object-Oriented Programming & Design Lecture 23
Throw List • One can restrict the types of exceptions that can be thrown in a function by specifying a throw list as part of the function prototype. For example void myFunction(void) throw(RangeErr,DivideByZero) {...} • If one throws a different type of exception than those in the list, the system function unexpected is called, which (by default) calls terminate • An empty throw list (i.e., throw()) specifies that any exceptions thrown by the function will trigger a call to unexpected • Handout #12
Polymorphism • Polymorphous: Having, or assuming various forms, characters, or styles • From greek roots, poly = many, and Morphos = form (Morphus was the greek god of sleep, who could assume many forms, and from which we derive the name Morphine, among other things) • American Heritage Dictionary (polymorphism) • 1. Biology. The occurrence of different forms, stages, or types in individual organisms or in organisms of the same species, independent of sexual variations • 2. Chemistry. Crystallization of a compound in at least two distinct forms. In this sense, also called pleomorphism • In OOP, polymorphism is when variables or functions have more than one form
Polymorphic Variables • Polymorphic variables, or untyped variables, are variables that have no type associated with them • Rather, type is associated with the data stored in the variables. Thus, the variable can hold values of different types during the course of execution • LISP & Smalltalk directly support polymorphic variables • The most common polymorphic variable is the one that holds the receiver during the execution of a method • Called this in C++ and Java, self in Smalltalk and Objective-C, current in Eiffel
Polymorphic Variables • C++ provides limited support for polymorphic variables in the form of class pointer conversions • C++ permits one to treat base classes as compatible abstractions of derived classes • This allows one to store the address of a derived class instance in a base class pointer variable
Polymorphism & Typing • Polymorphic Code (functional polymorphism) may be invoked with variables of different type (writing almost at a pseudo-code level) • Dynamically Typed Languages: code is polymorphic (almost by definition) • Statically Typed Languages: code restricted to declared type of variables (a priori) • Main challenge: polymorphism in statically typed languages • Expressive power • Safety
Functional Polymorphism • Functional polymorphism exists when a function or procedure has more than one form • Two types of functional polymorphism are • Pure polymorphism • Ad hoc polymorphism
Pure Polymorphism • A polymorphic method (also called pure polymorphism) occurs when a polymorphic variable is used as an argument • Different effects, which vary depending upon the argument, are formed by using different types of value
Ad hoc Polymorphism • Ad hoc: • 1. For the specific purpose, case, or situation at hand and for no other: a committee formed ad hoc to address the issue of salaries • 2. Formed for or concerned with one specific purpose: an ad hoc compensation committee • 3. Improvised and often impromptu: On an ad hoc basis, Congress has placed ceilings on military aid to specific countries
Ad hoc Polymorphism • Polymorphism is over finitely few shapes • Often, very few • Different shapes are generated manually, or semi-manually • No unifying common ground to all shapes, other than designer’s intentions • Uniformity is a coincidence, not a rule
Overloading Polymorphism • User or system overloads an identifier or operator to work with different types • E.g., C++’s user-defined overloading of the function name max double max(double d1, double d2); char max(char c1, char c2); char* max(char* s1, char* s2); • E.g., C++’s user-defined overloading of the += operator class Rational { public: Rational(double); const Rational& operator+=(const Rational& other); ... };
A Definition of Overloading • We say a term is overloaded if it has two or more meanings • Most words in natural languages are overloaded, and confusion is resolved by means of context • Same is true of OO languages • There are two important classes of context that are used to resolve overloaded names • Overloading based on scopes • Overloading based on type signatures
Interclass Overloading • Interclass overloading exists when different implementations of a function exist in different classes (or scopes) • In this case, the fully-scoped name of the function is sufficient to distinguish it from other implementations with the same function name
Intraclass Overloading • Intraclass overloading exists when different implementations of a funciton exist within the same class (or scope) • In C++, implementations are distinguished from one another by their fully-scoped names and their signatures
Distinguishing C++ Functions • The following rules are used to distinguish functions from one another in C++ • A function call first chooses from among all functions of that name, within the scope specified, those for which the argument types match the parameter types or for which a set of conversions exist • The set of functions that best match the call is calculated; if the set has more than one element, ambiguity exists
Distinguishing C++ Functions void setAngle(int degrees) void setAngle(float radians) int i = 45; float f = 3.1415; setAngle(i); // Okay setAngle(f); // Okay setAngle(3.1415); // OOPS!
Stream Output in C++ • Stream output is a good example of the power of overloading. Every primitive type has a different stream output function ostream& operator<<(ostream& destination, int source); ostream& operator<<(ostream& destination, short source); ostream& operator<<(ostream& destination, long source); ostream& operator<<(ostream& destination, char source); ostream& operator<<(ostream& destination, char* source); // ... and so on
Coercion Polymorphism • Polymorphism arising from the existence of built-in or user-defined coercions between types int pi = 3.14150; // Built-in coercion from double to int float x = ‘\0’; // Built-in coercion from char to float extern sqrt(float); x = sqrt(pi); // Built-in coercion from int to double and // built-in coercion from double to float
Coercion Polymorphism class Rational { public: Rational(double); operator double(void); ... }; Rational r(2); // Built-in coercion from int to double // and user-defined coercion from double // to Rational cout << sqrt(r); // User-defined coercion from Rational // to double (also C++’s user // overloading of the << operator)