22
POLYMORPHISM Michael Heron

2CPP10 - Polymorphism

Embed Size (px)

DESCRIPTION

This is an intermediate conversion course for C++, suitable for second year computing students who may have learned Java or another language in first year.

Citation preview

Page 1: 2CPP10 - Polymorphism

POLYMORPHISMMichael Heron

Page 2: 2CPP10 - Polymorphism

Introduction• The last of the three fundamental pillars of object

orientation is the principle of polymorphism.• It’s also the most abstract and difficult to initially see the benefits of.

• In the C++ model of polymorphism, it is inextricably tied up in the idea of inheritance.• They go together, hand in hand.

Page 3: 2CPP10 - Polymorphism

Polymorphism• The word Polymorphism comes from the Greek.

• Poly meaning ‘parrot’• Morph meaning ‘small man made of plasticine’.

• In basic terms, it means:• To treat a specialised object as an instance of its more general

case.

• For example, a Circle is a Circle.• But in a more general way, it’s also a shape.

Page 4: 2CPP10 - Polymorphism

The Scenario• We’re going to explore the topic of polymorphism through

a simple example program.• It relates to the relationship between two classes – an Employee

and a Manager.

• They are very similar except:• Managers can hire and fire• Employees cannot.

Page 5: 2CPP10 - Polymorphism

The Employee Classclass Employee {private: int payscale;public: int query_payscale(); void set_payscale (int p); bool can_hire_and_fire();};

#include "Employee.h"

bool Employee::can_hire_and_fire(){ return false;}

void Employee::set_payscale(int val) { payscale = val;}

int Employee::query_payscale() { return payscale;}

Page 6: 2CPP10 - Polymorphism

The Manager Classclass Manager : public Employee {public: bool can_hire_and_fire();};

#include "Manager.h"

bool Manager::can_hire_and_fire() { return true;}

Page 7: 2CPP10 - Polymorphism

The Program

#include <iostream>#include "Employee.h"#include "Manager.h"

using namespace std;

int main(int argc, char** argv) {

Employee *emp = new Employee(); Manager *man = new Manager();

cout << "Employees hiring and firing rights:" << emp->can_hire_and_fire() << endl; cout << "Managerss hiring and firing rights:" << man->can_hire_and_fire() << endl;

return 1}

Page 8: 2CPP10 - Polymorphism

The Output• So far, it’s pretty straightforward.

• Output for employees is 0.• False

• Output for managers is 1.• True.

• So it is written, so shall it be.• The polymorphism comes in when when we want to do something

a little more arcane.• Make a pointer to a base class point to am object of a more specialised

class.

Page 9: 2CPP10 - Polymorphism

Polymorphism#include <iostream>#include "Employee.h"#include "Manager.h"

using namespace std;

int main(int argc, char** argv) { Employee *emp = new Employee(); Manager *man = new Manager(); Employee *poly = new Manager(); cout << "Employees hiring and firing rights:" << emp->can_hire_and_fire() << endl; cout << "Managers hiring and firing rights:" << man->can_hire_and_fire() << endl; cout << "Polymorphic hiring and firing rights:" << poly->can_hire_and_fire() << endl; return 1;}

Page 10: 2CPP10 - Polymorphism

And…?• What happens now?

• In Java, it calls the most specialised version of the method.• It would call the one defined in Manager.

• In C++, it calls the method as defined in the class that is referenced by the pointer.• It would call the one defined in Employee.

• Okay, great – but so what?

Page 11: 2CPP10 - Polymorphism

The Power• The power comes from when we have many different

classes that extend from a common core.• Rather than coding special conditions for each of them, we code

for the base class.

• This greatly reduces the amount of work that a developer has to do.• And properly distributes the responsibility for implementing

functionality.

Page 12: 2CPP10 - Polymorphism

Virtual Functions• However, much of this is based on the idea that we can

trust a generalised reference to execute the most appropriate method.• As is done in Java

• C++ requires us to define a function as virtual if we want this behaviour.• From this point on, it becomes a virtual function and behaves in

the way we would expect from Java.

Page 13: 2CPP10 - Polymorphism

Modified Class Definitionclass Employee {private: int payscale;public: int query_payscale(); void set_payscale (int p); virtual bool can_hire_and_fire();};

Page 14: 2CPP10 - Polymorphism

How Do Virtuals Work?• When an object is created from a class, C++ creates a

lookup table for virtual functions.• This is in addition to all other data stored.

• Each virtual function has an entry in this table.• When you create the object with new, the entry is updated with a

reference to the appropriately specialized implementation.

• Each virtual method you declare increases the size of this table.• And thus size of the objects and processing time.

Page 15: 2CPP10 - Polymorphism

Clerical Staff#include "Employee.h"

class Clerical: public Employee {public: bool can_hire_and_fire(); void file_papers();};

#include "Clerical.h"

bool Clerical::can_hire_and_fire() { return false;}

void Clerical::file_papers() { // Something Something}

Page 16: 2CPP10 - Polymorphism

Modified Scenario• Two classes stem from the same root.

• Employee

• Using the Power of Polymorphism, we can treat them as instances of the base class.• We can manipulate them as if they were just Employees.• This means that we can’t make use of methods defined in the

specialised classes.• Only what we can guarantee is implemented by virtue of the class

hierarchy.

Page 17: 2CPP10 - Polymorphism

New Codeusing namespace std;

void set_payscale (Employee* emp, float amount) { emp->set_payscale (amount);}

int main(int argc, char** argv) { Employee *emp = new Employee(); Manager *man = new Manager(); Clerical *cler = new Clerical(); cout << "Employees hiring and firing rights:" << emp->can_hire_and_fire() << endl; cout << "Managers hiring and firing rights:" << man->can_hire_and_fire() << endl; cout << "Clerical hiring and firing rights:" << cler->can_hire_and_fire() << endl;

set_payscale (cler, 15000.0); set_payscale (man, 25000.0);

cout << "Clerical payscale: " << cler->query_payscale() << endl; cout << "Manager payscale: " << man->query_payscale() << endl; return 1;}

Page 18: 2CPP10 - Polymorphism

The Employee Class• The Employee class is now something we don’t really

want people using it.• It’s a common core, not a fully fledged object in its own right.

• In the next lecture, we’ll look at how we can prevent people making use of it directly.• We’ll also look at ways other than inheritance to provide a structure

for objects.

Page 19: 2CPP10 - Polymorphism

Benefits of Polymorphism• One of the benefits that comes from polymorphism is the

ease of processing lists of objects.• We don’t need a separate queue for Managers and Clerical staff• We just need one queue of employees

• We can iterate over each of these, provided we are making use of base functions.

Page 20: 2CPP10 - Polymorphism

Benefits of Polymorphismusing namespace std;

void set_payscale (Employee* emp, float amount) { emp->set_payscale (amount);}

int main(int argc, char** argv) {

Employee *emp = new Employee();

Employee **emps = new Employee*[2];

emps[0] = new Manager(); emps[1] = new Clerical();

for (int i = 0; i < 2; i++) { set_payscale (emps[i], 20000.0); cout << "Payscale for " << i << " is " << emps[i]->query_payscale() << endl; }

return 1;}

Page 21: 2CPP10 - Polymorphism

Benefits of Polymorphism• Polymorphism manages the complexity of the inheritance

model and lets you provide custom handling in the classes themselves.

• You don’t need:• if (it’s a manager) { do_this(); } else if (it’s a clerical)

{ do_this_other_thing() }

• One method, properly designed, can handle all the heavy lifting.• This does require the use of a clean, well designed object

hierarchy.

Page 22: 2CPP10 - Polymorphism

Summary• Polymorphism is the last of the three pillars of object

oriented programming.• The most powerful, but also the most abstract.

• You’re not really expected to ‘get it’ just yet.• We’ll return to the topic in later lectures.

• In the next lecture we’re going to continue discussing some of the ways in which we can enforce structure on our unruly objects.