Inheritance and Polymorphism

advertisement
Object Oriented Programming
Inheritance and
Polymorphism
Dr. Mike Spann
m.spann@bham.ac.uk
Contents







Base classes and derived classes
Example – a BankAccount class
Polymorphism and Object Oriented Programming
Abstract classes
Generic Programming
Polymorphism and OOP
Summary
Base classes and derived classes

Inheritance is a fundamental requirement of
oriented programming

It allows us to create new classes by refining
existing classes

Essentially a derived class can inherit data
members of a base class

The behaviour of the derived class can be
refined by redefining base class member
functions or adding new member function

A key aspect of this is polymorphism where a
classes behaviour can be adapted at run-time
Base classes and derived classes



We can think of many examples in real life of how
a (base) class can be refined to a set of (derived)
classes
For example a Polygon class can be refined to be a
Quadrilateral which can be further refined to be a
Rectangle
We can think of these classes as following an IS-A
relationship
 A Quadrilateral IS-A Polygon
 A Rectangle IS-A Quadrilateral
Base classes and derived classes
Base class
Shape
Bank Account
Student
Vehicle
Filter
Derived class
Triangle, Circle,
Rectangle
Current, Deposit
Undergraduate,
Postgaduate
Car, Truck, Bus
Low-pass, Band-pass,
High-pass
Example – a BankAccount class


An BankAccount base class models basic
information about a bank account

Account holder

Account number

Current balance
Basic functionality

Withdraw money

Deposit money
public class
{
private
private
private
BankAccount
int accountNumber;
string accountHolder;
int balance;
public BankAccount(int n,string name ,int b)
{
accountNumber = n;
accountHolder = name;
balance = b;
}
public int AccountNumber { // accountNumber property}
public string AccountHolder { // accounHolder property}
public int Balance { // balance property}
public void withdraw(int amount)
{
if (balance>amount)
balance-=amount;
}
public void deposit(int amount) { balance+=amount;}
}
Example – a BankAccount class

We can consider refinements to our Account
class


CurrentAccount

Can have an overdraft facility

No interest paid
DepositAccount

Pays interest on any balance

No overdraft facility
Example – a BankAccount class

We will create our refined classes using inheritance from
the BankAccount base class

Classes CurrentAccount and DepositAccount inherit the
basic attributes (private members) of account


accountNumber

accountHolder

balance
Also, new attributes are added

overdraftFacility

interestRate
Example – a BankAccount class

In order to implement the derived classes, we need to
consider private/public access between base and derived
classes

public member functions of the base class become
public member functions of the derived class

private members of the base class cannot be accessed
from the derived class
 Obvious otherwise encapsulation could be easily
broken by inheriting from the base class

Begs the question, how do we initialise derived class
objects?
Example – a BankAccount class

Base class methods and properties are
accessed through the base keyword
 base(.....) refers to the base class
constructor
 base.aMethod(.....) refers to a method of
the base class
 base.aProperty refers to a property of the
base class
class CurrentAccount : BankAccount
{
private int overdraftFacility;
public CurrentAccount(int n, string name, int b, int ov) : base(n, name, b)
{
overdraftFacility = ov;
}
public override void withdraw(int amount)
{
if (base.Balance - amount > -overdraftFacility)
base.Balance -= amount;
}
}
class DepositAccount : BankAccount
{
private float interestRate;
public DepositAccount(int n, string name, int b, float rate) : base( n, name,b)
{ interestRate = rate; }
float calcInterest()
{
float interest = base.Balance * interestRate;
base.Balance += (int)(interest);
return interest;
}
}
Example – a BankAccount class
CurrentAccount
DepositAccount
accountNumber
accountHolder
balance
accountNumber
accountHolder
balance
deposit()
withdraw()
deposit()
withdraw()
overdraftFacility
interestRate
withdraw()
calcInterest()
Example – a BankAccount class

We can see that in both derived classes we need to access
the balance instance field

We can do this directly (without using a public method or
property) by making balance a protected member of the
base class

A protected class member is one that can be accessed by
public member functions of the class as well as public
member functions of any derived class

Its half way between private and public

Encapsulation is then broken for classes in the
inheritance hierarchy and thus must be used where
performance issues are critical
Example – a BankAccount class
Class member
Can be accessed from
private
public member
functions of same class
protected
public member
functions of same class
and derived classes
Anywhere
public
public class BankAccount
{
private int accountNumber;
private string accountHolder;
protected int balance;
public BankAccount(int n,string name ,int b)
{
accountNumber = n;
accountHolder = name;
balance = b;
}
public int AccountNumber { // accountNumber property}
public string AccountHolder { // accounHolder property}
public int Balance { // balance property}
public void withdraw(int amount)
{
if (balance>amount)
balance-=amount;
}
public void deposit(int amount) { balance+=amount;}
}
class CurrentAccount : BankAccount
{
private int overdraftFacility;
public CurrentAccount(int n, string name, int b, int ov) : base(n, name, b)
{
overdraftFacility = ov;
}
public override void withdraw(int amount)
{
if (balance - amount > -overdraftFacility)
balance -= amount;
}
// balance is protected
}
class DepositAccount : BankAccount
{
private float interestRate;
public DepositAccount(int n, string name, int b, float rate) : base( n, name,b)
{ interestRate = rate; }
float calcInterest()
{
float interest = balance * interestRate;
balance += (int)(interest);
return interest;
}
}
Polymorphism and Object
Oriented Programming
Polymorphism is the key concept in object
oriented programming
 Polymorphism literally means many forms
 Essentially we are able to get many
different types of object behaviour from a
single reference type
 This enables us to write easily extensible
applications

Polymorphism and Object
Oriented Programming


For example in a computer game that simulates
the movement of animals we can send ‘move’
commands to different types of animal
We send the commands via an animal reference
which is the base class for the different animal
types
 But each type behaves differently once it
receives the command
 Such an approach leads to a readily extendable
application
Polymorphism and Object
Oriented Programming
Application
animal
Move
Polymorphism and Object
Oriented Programming
Polymorphism is implemented through
references to objects
 We can assign base class object references
to any derived class object

BankAccount acc1 = new CurrentAccount(12345, "John Smith", 1000, 500);
BankAccount acc2 = new DepositAccount(54321, "Bill Jones", 2000, 5.0);
Polymorphism and Object
Oriented Programming
CurrentAccount
acc1
12345
John Smith
1000
deposit()
withdraw()
500
withdraw()
Polymorphism and Object
Oriented Programming
DepositAccount
acc2
54321
Bill Jones
2000
deposit()
withdraw()
5.0
calcInterest()
Polymorphism and Object
Oriented Programming
We can see that in the case of the reference
to a CurrentAccountObject object, method
withdraw() is overidden in the derived class
 The question is, which one is called at
runtime?

public class BankAccountTest
{
static void Main(string[] args)
{
BankAccount acc1 = new CurrentAccount(12345, "John Smith“,1000, 500);
acc1.withdraw(250);
}
}
// Which withdraw()?
Polymorphism and Object
Oriented Programming
CurrentAccount
acc1
accountNumber
accountHolder
balance
deposit()
withdraw()
overdraftFacility
withdraw()
Which one
is called?
Polymorphism and Object
Oriented Programming


Clearly the behaviour of the object to the
‘withdraw’ message is important
 The derived class behaviour takes into account
the overdraft facility
We must look at the definitions of the withdraw()
method in the base and derived classes
 The base class withdraw() method is overridden
by the derived class method if the base class
method is declared as virtual and the derived
class method is declared as override
Polymorphism and Object
Oriented Programming
public class BankAccount
{
//……
public virtual void withdraw(int amount)
{
if (balance - amount > -overdraftFacility)
balance -= amount;
}
}
public class CurrentAccount : BankAccount
{
private int overdraftFacility;
public CurrentAccount(n, name, b) {…}
public override void withdraw(int amount)
{
if (balance - amount > -overdraftFacility)
balance -= amount;
}
}
Polymorphism and Object
Oriented Programming

Because withdraw() in the derived class is
declared as an override function of the virtual
function in the base class, the correct behaviour is
obtained
public class BankAccountTest
{
static void Main(string[] args)
{
BankAccount acc1 = new CurrentAccount(12345, "John Smith“,1000, 500);
acc1.withdraw(250);
}
}
// Calls the CurrentAccount withdraw() method
Polymorphism and Object
Oriented Programming



In Java, polymorphism (overriding the base class
implementation) is the default behaviour
In C++, the virtual keyword is used but no
override keyword
C# also has a keyword sealed for a base class
method which can’t be overriden
 Methods can also be declared override and
sealed indicating that they override a base class
method but can’t themselves be overriden
Abstract classes

In our example classes, the withdraw()
method of our BankAccount was declared as
a virtual function
 We were able to provide a sensible
implementation of this function
 This implementation could be regarded as
default behaviour if the function was not
overridden in derived classes
Abstract classes

If the method called can’t be resolved in the
derived class, it is delegated back to the
default base class method
public class BankAccountTest
{
static void Main(string[] args)
{
BankAccount acc1 = new CurrentAccount(12345, "John Smith“,1000, 500);
acc1.withdraw(250);
// Calls the CurrentAccount withdraw() method
BankAccount acc2 = new DepositAccount(54321, “Bill Jones“,2000, 5.0);
acc2.withdraw(100);
}
}
// Calls the BankAccount withdraw() method
Abstract classes

Abstract classes arise when there is no sensible
implementation of the virtual functions in the base
class


Base class virtual functions are always
overridden by derived class implementations
In this case, we simply declare the virtual function
as abstract but provide no implementation

A class containing at least one abstract function
must be declared an abstract class
Abstract classes


As an example, suppose we wanted to design a
hierarchy of shape classes for a computer graphics
application
Shape is an abstract concept
 There is no sensible way we can implement
functions to draw a shape or compute the area
of a shape
 It is natural to make such functions abstract
 We can derive concrete classes from shape and
provide implementations in the override
functions
Abstract classes
public abstract class Shape
{
private int xpos;
private int ypos;
public abstract void draw();
public abstract double area();
public virtual void move(int x, int y)
{
xpos+=x;
ypos+=y;
}
}
Abstract classes
public class Square : Shape
{
private int side;
public Square(int s) {side=s;}
public override void draw() { }
public override double area() { return side*side; }
}
public class Circle : Shape
{
private int radius;
public Circle(int r) { radius = r; }
public override void draw() { }
public override double area() { return System.Math.PI*radius*radius;}
}
Abstract classes

We can’t create Shape objects but we can
declare Shape references and assign them to
derived class objects
using System;
class ShapeTest
{
static void Main(string[] args)
{
Shape sq = new Square(10);
Shape c = new Circle(5);
System.Console.WriteLine("Area of square= " + sq.area());
System.Console.WriteLine("Area of circle= " + c.area());
}
}
Generic programming




Generic programming refers to performing
operations on different types using a single piece
of code
 Examples include the application of searching
and sorting algorithms to different data types
In Java, this is done using polymorphism and the
fact that all types are ultimately derived from a
superclass object
In C++ it is normally done using templates
C# provides both mechanisms for generic
programming
 We will look at an example of generic
searching using polymorphism
Generic programming

Suppose we want a generic search algorithm to
search for any kind of object in an array

Class object provides an Equals() method to test
whether one object is equal to another


Simply checks if the 2 object references point
to the same area of memory

Not very useful in practice
We need to provide an Equals() method in the
class of the object we are searching for

Polymorphism does the rest!
Generic Programming

In the following example we are searching
for a BankAccount object in an array

The search is based on the account
number

Class SearchAlg provides a linearSearch
method which carries out the search

We have provided an implementation of
Equals() in class BankAccount which
overrides the Equals() method in object
public class
{
private
private
private
BankAccount
int accountNumber;
string accountHolder;
int balance;
public BankAccount(int n,string name ,int b)
{
accountNumber = n;
accountHolder = name;
balance = b;
}
public int AccountNumber { // accountNumber property}
public string AccountHolder { // accounHolder property}
public int Balance { // balance property}
public void withdraw(int amount)
{
if (balance>amount)
balance-=amount;
}
public void deposit(int amount) { balance+=amount;}
public override bool Equals(object obj)
{
BankAccount b = (BankAccount) obj;
return (accountNumber==b.accountNumber);
}
}
Generic Programming
using System;
public class SearchAlg
{
public static int linearSearch(object[] a, object b)
{
int n=a.Length;
for (int i=0; i<n; i++)
{
if (a[i].Equals(b))
return i;
}
return -1;
}
}
Generic Programming
using System;
public class BankAccountTest
{
static void Main(string[] args)
{
BankAccount[] b = new BankAccount[3];
b[0]=new BankAccount(12345, "John Smith",100);
b[1]=new BankAccount(13579, "Bill Jones",200);
b[2]=new BankAccount(87654, "Paul Brown",300);
BankAccount bt=new BankAccount(13579, "JonesB", 700);
int index=SearchAlg.linearSearch(b,bt);
Console.WriteLine("Account found at index " + index);
}
}
Polymorphism and OOP


Polymorphism is a key feature of object oriented
programming
Complex systems are able to be easily extended
 The extendibility is provided by defining new
classes within an inheritance hierarchy
 Objects of these new classes are accessed
through a base class reference
 These objects add new behaviours to the system
through a common interface to the application
(the base class virtual functions)
Polymorphism and OOP

For example we could extend the list of
animals to which we can send ‘move’
messages in our video game application
 Each animal is responsible for its own
movement code which can easily ‘plugin’ to the main application
 Thus the application is easily extended
with minimal changes to the main
application code
Polymorphism and OOP
animal
Move
.
.
Summary




We have looked at how we can extend existing classes
through the idea of inheritance
We have seen how, by accessing derived classes through a
base class pointer, object behaviour is determined at run
time through polymorphism
We have looked at abstract classes where there is no
obvious implementation of base class virtual methods
 These methods are always overriden by derived class
methods
We have looked at the significance of polymorphism in
object orientation
 Object oriented applications are easily extended with
additional code mainly confined to new derived classes
Download