Vous êtes sur la page 1sur 46

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 Withdraw money Deposit money

Basic functionality

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
Pays interest on any balance No overdraft facility

DepositAccount

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
accountNumber accountHolder balance deposit() withdraw()

DepositAccount

accountNumber accountHolder balance


deposit() withdraw()

overdraftFacility withdraw()

interestRate 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 private protected Can be accessed from public member functions of same class 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; } } 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; } }

// balance is protected

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

Which one is called?

withdraw()

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()); } }

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

Vous aimerez peut-être aussi