CS 596 OODP
Polymorphism
[To Lecture Notes Index]
San Diego State University -- This page last updated November 16, 1995
Contents of Polymorphism Lecture
- Polymorphism
- Hot Shot Polymorphism and C++
- How to Increase the use of Pure Polymorphism
- Rules for Finding Standard Protocols
Polymorphic many forms
Polymorphic Object
- Programming entity that is permitted to hold values of differing
types
Levels of Polymorphism
- Pure (Parametric) Polymorphism
- An entity has more than one form
- Ad Hoc Polymorphism (Overloading)
- Different entities have the same name
Algorithm Analogy
- The sort algorithm works on may different types
-
-
- Verses Pascal implementation of a sort algorithm
Polymorphic Objects
A programming object (variable) can hold values of different types.
Source of most of polymorphism in OOPL
Dynamically Bound languages
- Smalltalk, Objective-C, CLOS
- All objects are potentially polymorphic
- x := 5;
- x := 5.5;
- x := 'This is a string';
C++
- Requires use of pointers
- class A { ... }
- class B : public A { ... }
-
- A* polyVariable;
-
- polyVariable = new A;
-
- polyVariable = new B;
Simple Polymorphism and C++
#include <iostream.h>
class Top {
public:
void virtual DoIt();
};
void Top::DoIt() {
cout << "Top" << endl;
}
class Bottom : public Top {
void virtual DoIt();
};
void Bottom::DoIt() {
cout << "Bottom" << endl;
}
main() {
Top* WhyMe = new Top;
WhyMe->DoIt(); // prints "Top"
WhyMe = new Bottom;
WhyMe->DoIt(); // prints "Bottom"
}
#include <iostream.h>
class Top {
public:
void DoIt();
void virtual FunPart() {cout << "Part1 in Top" << endl;}
};
void Top::DoIt() {
cout << "Top" << endl;
FunPart();
}
class Bottom : public Top {
void virtual FunPart();
};
void Bottom::FunPart() {
cout << "This is it" << endl;
}
main() {
Top* WhyMe = new Top;
WhyMe->DoIt(); // prints "Top \n Part1 in Top"
WhyMe = new Bottom;
WhyMe->DoIt(); // prints "Top \n This is it"
}
Polymorphism
main()
{
Account* customer;
customer = createNewAccount();
customer->Transaction(amount);
}
Polymorphism
class Account {
public:
void virtual Transaction(float amount)
{ balance += amount;}
Account(char* customerName, float InitialDeposit = 0);
protected:
char* name;
float balance;
}
class JuniorAccount : public Account {
public: void Transaction(float amount) {// put code here}
}
class SavingsAccount : public Account {
public: void Transaction(float amount) {// put code here}
}
Account* createNewAccount()
{
// code to query customer and determine what type of
// account to create
};
main()
{
Account* customer;
customer = createNewAccount();
customer->Transaction(amount);
}
Hot Shot Polymorphism
class Account {
public:
void Transaction(float amount);
void virtual TransactionSubpartA();
void virtual TransactionSubpartB();
void virtual TransactionSubpartC();
}
void Account::Transaction(float amount) {
TransactionSubpartA(); TransactionSubpartB();
TransactionSubpartC(); // EvenMoreCode;
}
class JuniorAccount : public Account {
public: void virtual TransactionSubpartA(); }
class SavingsAccount : public Account {
public: void virtual TransactionSubpartC(); }
Account* customer;
customer = createNewAccount();
customer->Transaction(amount);
Polymorphism
The Good
Making modifications to program require:
- Adding new subclasses
-
- Changing code that creates objects
Account* customer;
customer = createNewAccount();
customer->Transaction(amount);
Polymorphism and C++
The Bad
The
root base class needs to "know" about operations in all subclasses
Account* customer;
customer = createNewAccount();
customer->Foo(); // compile error
Modular Design Rules
Avoid Case Statements
if X is a Account then
X.AccountUpDate()
else if X is a JuniorAccount then
X.JuniorAccountUpDate()
Case X
Account: X.AccountUpDate()
JuniorAccount: X.JuniorAccountUpDate()
end case
Use Polymorphism
X->Update()
where
Account class and JuniorAccount class have an Update operation
Supports:
Composability Continuity
Modular Design Rules
Small Is Beautiful
Operation Size
- Upper bound for average size of an operation
- Language
- Lines of Code
- Smalltalk
- 8
- C++
- 24
Class Size
- Average number of operations per class should be less than 20
-
-
- Large classes should be viewed with suspicion and held guilty of poor
design until proven innocent
-
-
Supports:
Decomposability Composability Understandability
Modular Design Rules
Small Is Beautiful - Continued
Keep the number of parameters per operations small
- Operations with few parameters are more likely to be usable in different
classes
-
-
-
Reduce the number of parameters by:
-
-
- Breaking an operation into several smaller operations
-
-
- Creating a new class that represents a group of arguments
Supports:
Decomposability Composability Understandability
* Polymorphic Objects
* Overloading of small chunks of code
Protocol
- Name and arguments of public operations of an object
Plug Compatible Objects
- Objects with the same protocol
-
-
Standard Protocol
Using the same name for similar processes
(To Encourage Pure Polymorphism)
* Use small operations
- Smalltalk methods average about 3 - 5 lines of code
Rules for Finding Standard Protocols
(To Encourage Pure Polymorphism)
* Reduce the number of arguments
- Methods with small number of arguments are more likely to be usable in
different classes
-
-
- Reduce number of arguments by:
-
- * Breaking a message into several smaller messages
-
- * Creating a new class that represents a group of arguments
Rules for Finding Standard Protocols
(To Encourage Pure Polymorphism)
* Eliminate case analysis
- *Checking class of an object
if (anObject class = integer) then
anObject.Foo;
else
anObject.Fee;
-
-
- Implement Foo in all relevant classes to perform the equivalent operation
-
anObject.Foo
- * Case analysis of values of variables
- Can be more difficult, but no less important
Rules for Finding Standard Protocols
(To Encourage Pure Polymorphism)
* Recursion introduction
- If an operation X is implemented by performing a similar operation on the
component of the receiver, then that operation should also be named X.
-
-
-
void OrderedLinkedList::add(int value)
{
cell *newCell;
newCell = new cell;
newCell->value = value;
listHead->add(*newCell);
};