Anda di halaman 1dari 47

Object Oriented Programming

Inheritance and
Polymorphism

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

Derived class
Triangle, Circle,
Rectangle

Account

Current, Deposit

Student

Undergraduate,
Postgaduate

Vehicle

Car, Truck, Bus

Filter

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

public

Anywhere

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 cant be overriden
Methods can also be declared override and
sealed indicating that they override a base class
method but cant 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 cant 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 cant 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());
}
}

Abstract classes

We can regard abstract classes as a glue which


binds related classes together and where we dont
have to worry about implementational details

They just have to present a common interface


Shape
Circle

Square
draw()
area()

Triangle

.......

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("Acount 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 plug-in 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