CSci 3081W: Program Design and Development
Lecture 07 – Polymorphism
The major difference between C and C++ is Object Oriented Programming.
Encapsulation
Inheritance
Polymorphism
C
No
No
No
C++
Yes
Yes
Yes
Done Done Today
Project Update: Virtual Drone Delivery Project Project Manager: Dan Orban
You will be assigned your Iteration 1 team on Friday, October 9th (same day the Iteration 1 UML is due)
For now, you should work closely with your current lab team to develop the UML diagram (this is so we can cross pollinate ideas)
Use Lucidchart to build your individual UML. Sign-in with your UMN Google account. (everyone builds their own diagram)
UML Template (File Duplicate to start from the template if desired)
https://z.umn.edu/uml_iteration1
Everyone should start working on their UML Design
UML Class Diagram Tutorial Tutorial: Lucidchart
LucidChart Tips and Tricks
¡ñ How to use Lucidchart.
¡ñ UML and C++ code relationships.
¡ñ How to start from the project UML diagram.
¡ñ The solution to Quiz 1.
Everyone should start working on their UML Design
Roadmap for Today Inheritance – The Tangled Web
Polymorphism
Introduction to Design Patterns
Spiders that spin webs are currently categorized as Orb Weavers.
Spiders that spin webs are currently categorized as Orb Weavers.
Orbicualariae
Biological systems are far more sophisticated than computer systems.
Base 4 System (nucleotides)
Base 22 System (amino acids)
Analogy:
DNA: Compiled program in Machine Language (with backup and copy solution)
RNA: Program Execution – instruction set (probabilistic)
Protein: Functions and Data Variables
Biological systems blow classical computing out of the water.
Human Genome has approximately 20,000 genes – protein coding sequences.
Genes are turned on or off based on a series of chemical processes but are regulated probabilistically: a number of genes are expressed at any given time (RNA seq)
Assuming just on or off, the number of possible states in the human body would be 2^20,000.
If we just had 300 genes in only 2 states, the number of possible states would be 2^300:
More than the number of atoms in the known universe!
Scientists have discovered web weaving exists in two separate parts of the biological hierarchy.
“Phylogenomic analysis of spiders reveals nonmonophyly of orb weavers.” Curr Biol. 2014 Aug 4;24(15):1772-7. DOI: 10.1016/j.cub.2014.06.035. Epub 2014 Jul 17.
“Tangled in a sparse spider web: single origin of orb weavers and their spinning work unravelled by denser taxonomic sampling.” Proc. R. Soc. B:2011
Scientists have discovered web weaving exists in two separate parts of the biological hierarchy.
This simply does not appear to be true according to DNA similarity analysis.
This is a more accurate categorization, but web spinning is strange.
From a computer science perspective this means two possible options if we try to model this using hierarchy alone. – Both are bad designs!
Design 1 – Web spinning in base class
From a computer science perspective this means two possible options if we try to model this using hierarchy alone. – Both are bad designs!
Design 1 – Web spinning in base class
¡ñ This doesn¡¯t make sense for webless spiders.
From a computer science perspective this means two possible options if we try to model this using hierarchy alone. – Both are bad designs!
Design 2 – Rewrite the spinWeb() function in several places.
From a computer science perspective this means two possible options if we try to model this using hierarchy alone. – Both are bad designs!
Design 2 – Rewrite the spinWeb() function in several places.
¡ñ Tons of work
¡ñ Error prone
¡ñ No code reuse (which is purpose of
inheritance)
Today we will talk about how to reconcile this problem from a computer science programming design perspective.
How can we design this system?
Today we will talk about how to reconcile this problem from a computer science programming design perspective.
C++ Solution: Use polymorphism and composition over inheritance.
Roadmap for Today
Inheritance – The Tangled Web
Polymorphism
Introduction to Design Patterns
What do all ducks share in common?
What is wrong with this picture?
cout << ¡°quack¡± << endl;
cout << ¡°I am swimming.¡± << endl;
cout << ¡°I am flying¡± << endl;
cout << ¡°I am a duck.¡± << endl;
Polymorphism allows subclasses to override functionality of the base class.
cout << ¡°quack¡± << endl;
cout << ¡°I am swimming.¡± << endl;
cout << ¡°I am flying¡± << endl;
cout << ¡°I am a duck.¡± << endl;
cout << ¡°I am a mallard.¡± << endl;
cout << ¡°I am a redhead duck.¡± << endl;
cout << ¡°Squeak!¡± << endl;
return;
cout << ¡°I am a rubber duck.¡± << endl;
We have already studied basic inheritance (so let¡¯s start there).
class Duck {
public:
void quack() { cout << "Quack" << endl; }
void swim() { cout << "Swim" << endl; }
void fly() { cout << "Fly" << endl; }
void display() { cout << "I am a duck." << endl; }
};
class MallardDuck : public Duck {
public:
void display() { cout << "I am a mallard duck." << endl; }
};
class RedheadDuck : public Duck {
public:
void display() { cout << "I am a redhead duck." << endl; }
};
class RubberDuck : public Duck {
public:
};
void quack() { cout << "Squeak!" << endl; }
void fly() { return; }
void display() { cout << "I am a rubber duck." << endl; }
We have already studied basic inheritance (so let¡¯s start there).
class Duck {
public:
void quack() { cout << "Quack" << endl; }
void swim() { cout << "Swim" << endl; }
void fly() { cout << "Fly" << endl; }
void display() { cout << "I am a duck." << endl; }
};
class MallardDuck : public Duck {
public:
void display() { cout << "I am a mallard duck." << endl; }
};
class RedheadDuck : public Duck {
public:
void display() { cout << "I am a redhead duck." << endl; }
};
class RubberDuck : public Duck {
public:
What is the output here?
int main() {
Duck duck;
duck.quack();
Duck someDuck = RubberDuck();
someDuck.quack();
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
return 0;
}
};
void quack() { cout << "Squeak!" << endl; }
void fly() { return; }
void display() { cout << "I am a rubber duck." << endl; }
We have already studied basic inheritance (so let¡¯s start there).
class Duck {
public:
void quack() { cout << "Quack" << endl; }
void swim() { cout << "Swim" << endl; }
void fly() { cout << "Fly" << endl; }
void display() { cout << "I am a duck." << endl; }
};
class MallardDuck : public Duck {
public:
void display() { cout << "I am a mallard duck." << endl; }
};
class RedheadDuck : public Duck {
public:
void display() { cout << "I am a redhead duck." << endl; }
};
class RubberDuck : public Duck {
public:
How can we make this say ¡°Squeak!¡±?
What is the output here?
int main() {
Duck duck;
duck.quack();
Duck someDuck = RubberDuck();
someDuck.quack();
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
return 0;
}
};
void quack() { cout << "Squeak!" << endl; }
void fly() { return; }
void display() { cout << "I am a rubber duck." << endl; }
Polymorphism allows us to override methods using virtual functions. (Poly)morphism = many forms
class BaseClass {
public:
virtual return_type function(params);
};
class DerivedClass : public BaseClass {
public:
return_type function(params);
};
Overrides base class implementation.
Polymorphism allows us to override methods using virtual functions.
class Duck {
public:
virtual void quack() { cout << "Quack" << endl; }
};
class RubberDuck : public Duck {
public:
void quack() { cout << "Squeak!" << endl; }
};
int main() {
Duck duck;
duck.quack();
Duck someDuck = RubberDuck();
someDuck.quack();
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
return 0;
How can we make this say ¡°Squeak!¡±?
}
Polymorphism allows us to override methods using virtual functions.
class Duck {
public:
virtual void quack() { cout << "Quack" << endl; }
};
class RubberDuck : public Duck {
public:
void quack() { cout << "Squeak!" << endl; }
};
int main() {
Duck duck;
duck.quack();
Duck* someDuck = new RubberDuck();
someDuck>quack();
delete someDuck;
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
return 0;
}
Why does this work?
Pointers use the actual object rather than making a copy.
// base class copy
int main()
{
// virtual functions and pointers
int main()
{
}
Duck duck;
duck.quack();
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
Duck someDuck = rubberDuck; // copy
someDuck.quack();
return 0;
Memory
}
Duck duck;
duck.quack();
RubberDuck rubberDuck = RubberDuck();
rubberDuck.quack();
Duck* someDuck = new RubberDuck();
someDuck>quack();
delete ducsomeDuckk2;
return 0;
Memory
Variable
duck
rubberDuck
someDuck
Value
RubberDuck()
Variable
duck
Value
Duck()
Duck()
Duck()
rubberDuck
someDuck
RubberDuck()
So what is the big deal?
Take away: We can call overridden methods from the base class!
Pure virtual functions enforce a contract, but don¡¯t allow ¡°instantiation¡± or an object (or ¡°creation¡± of an object)
class BaseClass {
public:
virtual return_type function(params) = 0;
};
class DerivedClass : public BaseClass {
public:
return_type function(params);
};
No implementation so we cannot create an object of type BaseClass.
Let¡¯s investigate this with ducks.
class Duck {
public:
virtual void display() = 0;
};
class RubberDuck : public Duck {
public:
Abstract class
Pure virtual function
};
void display() { cout << "I am a rubber duck." << endl; }
int main() {
Duck duck;
}
RubberDuck rubberDuck;
return 0;
Roadmap for Today
Inheritance - The Tangled Web
Polymorphism
Introduction to Design Patterns
Design Patterns are object oriented designs that increase flexibility.
The Gang of Four Book
Design Patterns are object oriented designs that increase flexibility.
https://www.dofactory.com/net/design-patterns
The Open/Closed Design Principle: Software should open to extension, but closed to modification.
What is wrong with this design?
The Open/Closed Design Principle: Software should open to extension, but closed to modification.
Adding a new shape requires a change in the Graphics Editor.
Not closed to change!
What is wrong with this design?
The Open/Closed Design Principle: Software should open to extension, but closed to modification.
How about this design?
What happens when you add a new shape?
The Open/Closed Design Principle: Software should open to extension, but closed to modification.
Closed to change and open to extension. Uses polymorphism!
Inheritance is not always the best tool to use. For example:
Inheritance sometimes makes designs more complex and inflexible. We have an even bigger problem that inheritance cannot solve!
Various web types:
A - Sheet
B - Funnel
C - Tangle (Cob) D - Orb
E - Tubular
Imagine the inheritance hierarchy.
The solution: use inheritance with polymorphism and composition.
This has the added benefit of allowing other organisms to reuse the same functionality.
Take away: for complex systems, composition is the way to go! This pattern is called the Strategy Pattern and examples are found
throughout the biological world.
https://www.dofactory.com/net/strategy-design-pattern
Roadmap for Today
Inheritance - The Tangled Web
¡ñ Inheritance alone can be problematic.
Polymorphism
¡ñ Polymorphism allows us to override functionality.
¡ñ Enables high cohesion and low coupling!
Design Patterns
¡ñ It is good design to favor composition over inheritance.
¡ñ The strategy pattern allows us to reuse functionality anywhere
within a class hierarchy.