Tải bản đầy đủ (.pdf) (32 trang)

Polymorphism potx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (938.99 KB, 32 trang )

Polymorphism
Chapter 7
Polymorphism is the ability that helps in executing
different operations in response to the same
message. In OOP, you can implement
polymorphism by creating more than one function
within a class that have the same name. The
difference in the functions lies in the number and the
types of parameters passed to each function.
This chapter introduces the concept of
polymorphism. It explains how to implement
function overloading and operator overloading.
In this chapter, you will learn to:
 Describe polymorphism
 Implement function overloading
 Implement operator overloading
Objectives

¤NIIT Polymorphism 7.3
The term polymorphism was derived from the Greek words ‘poly’ and ‘morphos’, which
mean ‘many’ and ‘forms’, respectively. In OOP, polymorphism is often expressed by the
phrase “one interface, multiple functions”. This expression means that polymorphism
allows one interface to be used for multiple functions. You can apply polymorphism for
reducing the complexity within the functions of a class of your program.
Polymorphism can either be static or dynamic. In static polymorphism the response to a
function is decided at compile time. In dynamic polymorphism the response to the
function is decided at run time.
Static polymorphism refers to an entity, which exists in various forms simultaneously.
The concept of static polymorphism is analogous to the role of a woman who can be a
wife, a mother, a daughter, a sister, and an executive at the same time.
The mechanism of linking a function with an object during compile time is called early


binding. It is also known as static binding.
C# uses two approaches to implement static polymorphism. These are:
 Function Overloading
 Operator Overloading
Function Overloading
This approach allows using the same name for two or more functions. Each redefinition of
a function must use different types of parameters, sequence of parameters, or a number of
parameters. The type, sequence, or number of parameters for a function is called the
function signature. When you have multiple functions with the same name, the compiler
identifies the function based on the parameters to the function.
Consider an example, to understand the benefit of function overloading where you need a
function that converts distance in kilometers to miles, and kilometers can either be an
integer or a float. One approach can be to have two functions of different names, as
shown in the following code:
int ConvertInteger(int km);
int ConvertFloat(float km);
Introducing Polymorphism
Static Polymorphism
7.4 Polymorphism ¤NIIT
N
ote
Another approach can be using function overloading. You can have two functions with
the same name but with different parameters, as shown in the following code:
int Convert(int km);
float Convert(float km);
Operator Overloading
This approach allows user-defined types such as structures and classes, to use overloaded
operators for easy manipulation of their objects. Operator overloading can be achieved by
defining the static member functions using the
operator keyword. For example, you can

redefine the + operator for a user-defined class
Hour to add the hour value of two class
objects. You can then add two Hour objects by using the +
operator.
The following code is an example showing the usage of operator (+):
Hour h1;
Hour h2;
Hour h3;
H3=H1+H2;
In dynamic polymorphism the decision about function execution is made at run time.
Dynamic polymorphism is more useful as compared to static polymorphism because
dynamic polymorphism gives much more flexibility for manipulating objects.
The mechanism of linking a function with an object at run time is called dynamic or late
binding. Dynamic binding supports virtual functions.
C# uses two approaches to implement dynamic polymorphism. These are:
 Abstract classes: Are the special type of base classes that consist of abstract class
members. All the class members that are derived directly from abstract classes must
implement all the abstract functions and properties.
 Virtual functions: Are the functions that do not really exist, however, appear to be
present in some parts of the program.
Abstract classes and virtual functions will be taught in detail in chapter 8.
Dynamic Polymorphism
¤NIIT Polymorphism 7.5
Function overloading is the most common way of implementing polymorphism. You can
implement function overloading by defining two or more functions in a class sharing the
same name. However, each definition of a function must differ in its function signature.
The following code is an example of function overloading:
using System;
namespace CalculateMax
{

class CalculateMax
{
public int Max(int number1, int number2)
{
if (number1 > number2)
{
return number1;
}
else
{
return number2;
}
}
public float Max(float number1, float number2)
{
if (number1 > number2)
{
return number1;
}
else
{
return number2;
}
}
}
class MaxCalc
{
static int Main(string[] args)
{
CalculateMax calc = new CalculateMax();

Console.WriteLine("{0}", calc.Max(5.4F, 8.6F));
//Both function calls differ
Console.WriteLine("{0}", calc.Max(19, 12));
//only in their parameters
Console.ReadLine();
return 0;
}
}
}
Implementing Function Overloading
7.6 Polymorphism ¤NIIT
In the preceding example, the function Max() displays the maximum of two numbers,
number1 and number2. The function Max() is overloaded by passing the integer and float
values to it.
The output of the preceding code is as follows.
Output of the Function Overloading Program
During a function call, a C# compiler needs to resolve the name of the function. The
signature of a function is defined by:
 The number of parameters. Consider the following example:
void AddNumber(int);
void AddNumber(int, float);
In the preceding code, there are two functions because the number of parameters is
different.
 The data types of parameters. Consider the following example:
void Display(int);
void Display(char);
In the preceding code, the two functions are different because the data type of their
parameters is different.
 The sequence of the parameters. Consider the following example:
void Display(int,char);

void Display(char,int);
Function Signature
¤NIIT Polymorphism 7.7
N
ote
In the preceding code, the two functions are different because their parameters are
specified in a different order.
The return type is NOT a part of a function's signature. Therefore, the following two
declarations cannot occur in the same class:
void display();
char display();
In addition to function overloading, you can also overload constructors.
Constructors can also be parameterized, and therefore, they can be overloaded.
Overloaded constructors are commonly used in C# to provide flexibility while creating an
object.
The following is an example of overloading constructors:
using System;
class CalculateNumber
{
private int number1, number2, total;
//Default constructor
public CalculateNumber()
{
number1= number2= total = 0;
}
public CalculateNumber(int num1, int num2) //Two-argument
//constructor
{
number1= num1;
number2= num2;

total = 0;
}
public void AddNumber()
{
total = number1 + number2;
}
public void DisplayNumber()
{
Console.WriteLine("The sum of two numbers is {0}", total);

}
}
class CalNum
{
Constructor Overloading
7.8 Polymorphism ¤NIIT
N
ote
static int Main(String[] args)
{
//Default constructor invoked
CalculateNumber cal1 = new CalculateNumber();
//Parameteric constructor
CalculateNumber cal2 = new CalculateNumber(4,3);
cal1.AddNumber(); //add() invoked to calculate sum of members
cal1.DisplayNumber();
cal2.AddNumber(); //add() invoked to calculate sum of members
cal2.DisplayNumber();
return 0;


}
}
In the preceding code, the default constructor is invoked for object cal1 because it is
created without any parameter. The parameterized constructor is invoked for
cal2 object
because it is created with parameters.
To see the output of the preceding program, press Ctrl+F5.
The output of the preceding code is as follows.
Output of the Constructor Overloading Program
¤NIIT Polymorphism 7.9
Problem Statement
Tim has to develop an application for a primary school. The application should accept the
month entered by the student and display the total number of days of that month.
Solution
To develop the required application, Tim needs to perform the following tasks:
1. Create a console-based application.
2. Build and execute an application.
Task 1: Creating a Console-Based Application
To create a console-based application, Tim needs to perform the following steps:
1. Select StartÆAll ProgramsÆMicrosoft Visual Studio 2005ÆMicrosoft Visual
Studio 2005. The Start Page - Microsoft Visual Studio window is displayed.
2. Select FileÆNewÆProject. The New Project dialog box is displayed.
3. Select the project type as Visual C# from the Project types pane and Console
Application from the Templates pane.
4. Type the name of the new project as PrimarySchool in the Name text box.
5. Specify the location where the new project is to be created as c:\chapter7\Activity1
in the Location combo box.
6. Click the OK button.
7. Open the Solution Explorer window and right-click the Program.cs file. The
shortcut menu is displayed.

8. Select the Rename option and type the new name as DayCount.cs.
9. Double-click the DayCount.cs file in the Solution Explorer window. The Code
view of the DayCount.cs file is displayed.
10. Replace the existing code with the following code:
using System;
namespace PrimarySchool
{
class DayCount
{
int Month;
int Year;
int Days;
Activity: Displaying Days Using Function
Overloading
7.10 Polymorphism ¤NIIT
public DayCount() //Constructor to initialize month and
year to 0
{
Month = 0;
Year = 0;
}
//Returns 1 if year is a leap year, else returns 0
public Boolean LeapYear()
{
if (Year % 4 == 0)
return true;
else
return false;
}
//Sets the month and year

public void setDate(int month1, int year1)
{
Year = year1;
Month = month1;
}
// Sets the month, overloaded function
public void setDate(int month1)
{
Month = month1;
Year = 2006;
}
//Returns the name of the month
public string monthName()
{
switch (Month)
{
case 1: return "January";
case 2: return "February";
case 3: return "March";
case 4: return "April";
case 5: return "May";
case 6: return "June";
case 7: return "July";
case 8: return "August";
case 9: return "September";
case 10: return "October";
case 11: return "November";
case 12: return "December";
default: return "Invalid Month Specified!";
}

}
//Sets the number of days in a month
public void setDays()
{
switch (Month)
¤NIIT Polymorphism 7.11
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
{
Days = 31;
break;
}
case 2:
{
Days = 28;
if (LeapYear())
Days = 29; //Assign 29 Days if leap year
break;
}
case 4:
case 6:
case 9:
case 11:
{

Days = 30;
break;
}
}
}
public void display()
{
string[] name = new string[25];
setDays();
Console.Write("The number of days in the month of " +
monthName());
Console.Write(" is " + Days);
}
static void Main(string[] args)
{
DayCount dayCount = new DayCount();
int month, year;
Console.WriteLine("Enter the month in number:");
month = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the year :");
year = Convert.ToInt32(Console.ReadLine());
dayCount.setDate(month, year);
dayCount.display();
Console.ReadLine();
}
}
}
7.12 Polymorphism ¤NIIT
Task 2: Building and Executing an Application
To build and execute the application perform the following steps:

1. Select BuildÆBuild Solution or press F6 to build the solution.
2. Select DebugÆStart Debugging or press F5 to execute the application.
3. Verify the output of the application.
The following window verifies the output of the executed program.
Output of the PrimarySchool Application
¤NIIT Polymorphism 7.13
The concept of overloading a function can also be applied to operators. Operator
overloading provides additional capabilities to C# operators when they are applied to
user-defined data types. Only the predefined set of C# operators can be overloaded.
Most built-in data types have predefined operators associated with them. For example, the
C# data types
int with the operators +, -, *, and / provides support for mathematical
operations. A class is an example of a user-defined data types. To make operations on a
user-defined data type is not as simple as the operations on a built-in data type. To use
operators with user-defined data types, they need to be overloaded according to a
programmer’s requirement.
The following is an example of the
Length class that implements the British standard of
measuring distance:
class Length
{
int iFeet;
float fInch;
public Length(int iFt, float fIn)
{
iFeet=iFt;
fInch=fIn;
}
void Disp_Len(void)
{

Console.WriteLine("Length = {0}’{1}", iFeet, fInch);

}
}
To add two distances stored in two objects of the Length class in the preceding example,
you need to invoke a function. Consider, you have defined a function named
Add_Dist.
The following is the code to invoke the function:
object3.Add_Dist(object1, object2);
In this case, object1 is added to object2 and the result is stored in object3.
You might also want to compare two distances. The following code compares two objects
of the
Length class, using the CompareDistance():
object1.CompareDistance(object2);
Implementing Operator Overloading
Need for Operator Overloading
7.14 Polymorphism ¤NIIT
In the preceding code, the member function CompareDistance() of object1 is invoked
with
object2 as a parameter. This function compares the data members of object1 with
those of
object2 and returns the difference between them.
Instead of using the
Add_Dist() to add two distances, it is easier to use the following
statement:
object3 = object1 + object2;
In the preceding code, object1, object2, and object3 are all objects of the Length class.
This code is an easier way of expressing your intent as opposed to a lengthy function call.
The objects of the
Length class can be compared as shown in the following code:

object1 > object2;
or
object1 < object2;
or
object1 == object2;
Users can understand the operator notation more easily than a function call because it is
closer to real-life implementation. Therefore, by associating a set of meaningful operators,
a user-defined data type can be manipulated in a conventional and simple form.
Associating operators with user-defined data types involves overloading them.
The following table describes the overload ability of the operators in C#.
Operators Description
+, -, ! , ~, ++ , These unary operators take one operand and can be
overloaded.
+, -, *, /, % These binary operators take two operands and can
be overloaded.
==, !=, <, >, <=, >= The comparison operators can be overloaded.
&&, || The conditional logical operators cannot be
overloaded directly, but they are evaluated using &
and | which can be overloaded.
+=, -=, *=, /=, %= The assignment operators cannot be overloaded.
=, ., ?:, ->, new, is, sizeof, typeof These operators cannot be overloaded.
Overload Ability of Operators
¤NIIT Polymorphism 7.15
N
ote
The comparison operators, if overloaded, must be overloaded in pairs; that is, if == is
overloaded, != must also be overloaded. The reverse is also true. Similarly, it is true
for < and >, and for <= and >=.
An operator can be overloaded by defining a function to it. The function for the operator
is declared by using the

operator keyword.
Operators may be considered as functions internal to the compiler. For example, the
expression
a+b may be taken as +(a,b). A programmer may also overload these functions
by writing the appropriate functions with similar signatures. Functions that specify the
additional task for the operators are called operator functions. The keyword
operator
along with the operator to be overloaded is used as the function name.
For example, to overload the
+ operator, the following syntax is used to define the
operator function:
<access specifier> className operator +(parameters)
{
//Code
}
Such a definition makes use of operators, realistic and easy to understand. For example, if
the ‘
+’ operator is overloaded for the class Length, then the process of adding two
distance objects will be a simple statement, which is
object1 + object2 for the user.
The compiler interprets the preceding statement as operator + (object1,object2),
where the operator function of the first operand is invoked with the second operand of the
operator.
Both unary and binary operators can be overloaded.
Unary operators act on a single operand. Some examples of unary operators are the
increment (++) and decrement ( ) operators.
Unary operators can be classified as:
 Simple prefix unary operators, for example the – (minus) operator
 Pre and post increment and decrement operators, for example the ++() prefix
increment operator

Overloading Unary Operators
7.16 Polymorphism ¤NIIT
Simple Prefix Unary Operators
A simple prefix unary operator may be defined by function that takes one parameter. For
example, in the following code the compiler resolves ‘
-object1’ as:
operator - (object1)
The operator – () function can be associated with the class by making it a member
function. The
operator – () function can be provided an object of the class as its
parameter. This effectively associates the class with the function.
The following code is an example of the overloading
- operator:
using System;
namespace Calculator
{
class Calculator
{
public int number1, number2;
public Calculator(int num1, int num2)
{
number1 = num1;
number2 = num2;
}
public static Calculator operator -(Calculator c1)
{
c1.number1 = -c1.number1;
c1.number2 = -c1.number2;
return c1;
}

public void Print()
{
Console.WriteLine(" number1=" + number1);
Console.WriteLine(" number2=" + number2);
Console.ReadLine();
}
}
class EntryPoint
{
static void Main()
{
Calculator calc = new Calculator(15, -25);
//using the overloaded – operator with the class object
calc = -calc;
calc.Print();
}
}
}
¤NIIT Polymorphism 7.17
The output of the preceding example is as follows.
Output of the – Operator Overloading Program
In the preceding code, - operator is overloaded to make the variables of class Calculator
negative. In the statement
calc = -calc, the – operator is used with the object of the
class
Calculator, which calls the operator overload method and makes the variables
negative.
Pre and Post Increment and Decrement Operators
The increment operator increments the current value of an operand by 1 and returns the
result. The decrement operator decrements the current value of an operand by 1 and

returns the result.
When the increment and decrement operators are used, the value of the variable is the
same after the operation is completed. The difference in the value of the variable between
the prefix and postfix notation is the order in which they are applied.
There are certain rules, which are applied when declaring the prefix and postfix notations;
the notations must be
public, static, and unary. The following is an example of the
increment operator for the
Watch struct:
struct Watch
{
private int val;

public static Watch operator++ (Watch parameter)
{
7.18 Polymorphism ¤NIIT
parameter.val++;
return parameter;
}

}
In C#, the single operator is used for both the prefix and postfix operators. The result of a
postfix notation is the value of the operand before it takes place. The following example
statements give the usage of postfix notation:
Watch w = new Watch(6);
Watch postFix = w++;
The preceding statements will result in assigning the value of variable w to variable
postFix and then incrementing the value of variable w.
The result of a prefix expression is the return value of the operator. The following
example statements give the usage of prefix notation:

Watch w = new Watch(6);
Watch preFix = ++w;
The preceding statements will result in incrementing the value of variable w and then
assigning the value of variable
w to object preFix.
The following is an example of overloading the pre increment and post increment
operator, using structures:
using System;
namespace OperatorOverload
{
struct NumberCount
{
public int i;
public NumberCount(int initval)
{
this.i = initval;
}
public static NumberCount operator ++(NumberCount arg)
{
arg.i++;
return arg;
}
}
class TestClass
{
static void Main(string[] args)
{
NumberCount Count1 = new NumberCount(1);
NumberCount Count2 = Count1++;
Console.WriteLine(Count1.i);

¤NIIT Polymorphism 7.19
N
ote
Console.WriteLine(Count2.i);
Count2 = ++Count1;
Console.WriteLine(Count1.i);
Console.WriteLine(Count2.i);
Console.ReadLine();
}
}
}
The output of the preceding example is as follows.
Output of the Overloading Increment Operator Program with Structs
You can also overload the prefix and postfix notations in classes.
The implementation of increment and decrement operator overloading is different in
classes as compared to structs.
Operators in Classes
The implementation of the increment operator used with
structs cannot be implemented
with classes. If
Watch is a class, assigning of variable w to postFix makes the variable
postFix refer to the same object as w. Updating w will automatically update postFix.
7.20 Polymorphism ¤NIIT
The following is an example of the implementation of the increment operator where
Watch is a class:
class Watch
{
private int val;
public Watch(int paraVal)
{

this.val = paraVal;
}

public static Watch operator++(Watch parameter)
{
return new Watch (parameter.val +1)
}

}
In the preceding example, notice the operator++ creates a new object based on the data
in the original object. The data in the new object is incremented but the data in the
original object is not affected. The following is an example to overload the increment
operator in both prefix and postfix forms using classes:
using System;
namespace OperatorOverload
{
class NumberCount
{
public int i;
public NumberCount(int initval)
{
this.i = initval;
}
public static NumberCount operator ++(NumberCount arg)
{
return new NumberCount(arg.i + 1);
}
}
class TestClass
{

static void Main(string[] args)
{
NumberCount Count1 = new NumberCount(1);
NumberCount Count2 = Count1++;
Console.WriteLine(Count1.i);
Console.WriteLine(Count2.i);
Count2 = ++Count1;
¤NIIT Polymorphism 7.21
Console.WriteLine(Count1.i);
Console.WriteLine(Count2.i);
Console.ReadLine();
}
}
}
The output of the preceding example is as follows.
Output of the Overloading Increment Operator Program with Class
Binary operators are operators that work with two operands. Examples of binary operators
include the arithmetic operators (+, -, *, /, %), arithmetic assignment operators (+=, -=,
*=, /=, %=), and comparison operators (<, >, <=, >=, =, !=). Overloading a binary
operator is similar to overloading a unary operator, except that a binary operator requires
an additional parameter.
You can overload simple binary operators. Binary operators are used, as shown in the
following code:
a <operator> b
In the preceding code, <operator> is a symbol that denotes a binary operator. C#
interprets the expression as:
operator <operator>(Object1,Object2);
Overloading Binary Operators
7.22 Polymorphism ¤NIIT
For example:

operator +(a,b);
The following code is an example of using simple binary operators:
using System;
using System.Collections.Generic;
using System.Text;
namespace BinaryOverload
{
class Calculator
{
public int number;
public Calculator()
{
number = 0;
}
public Calculator(int n)
{
number = n;
}
public static Calculator operator +(Calculator Calc1,
Calculator Calc2)
{
Calculator Calc3 = new Calculator(0);
Calc3.number = Calc2.number + Calc1.number;
return Calc3;
}
public void display()
{
Console.WriteLine("{0}", number);
}
}

class CalNum
{
static int Main(string[] args)
{
Calculator num1 = new Calculator(100);
Calculator num2 = new Calculator(50);
Calculator num3 = new Calculator();
num3 = num1 + num2;
num1.display(); //Displays 100
num2.display(); //Displays 50
num3.display(); //Displays 150
Console.ReadLine();
return 0;
}
}
}
¤NIIT Polymorphism 7.23
In the preceding code, the + operator is overloaded to add two objects of the Calculator
class. The operator function receives one object as a parameter. In the preceding code,
num1 is an object of a class, of which the operator is a member function. Object num2 is
passed as a parameter to the operator. When an overloaded operator is invoked, the object
on the left of the operator is a member and the object on the right of the operator is the
parameter.
The output of the preceding example is as follows.
Output of the Simple Binary Operators Program
7.24 Polymorphism ¤NIIT
Problem Statement
FunCity Land is a newly established amusement park located in West Virginia. Brad is a
chief technical officer of FunCity Land. He is currently working on a project related with
calculating distances. This project will calculate the distance to reach FunCity Land from

various locations because many visitors do not know the exact location of the park.
Brad needs to develop a program, which would enter a visitor’s location and the distance
traveled by the visitor. After analyzing the location and the distance traveled by the
visitor, the program should display the remaining distance and the total distance traveled.
Help Brad to develop an application by overloading the binary operator (+).
Solution
To develop the required application, Brad needs to perform the following tasks:
1. Create a console-based application.
2. Build and execute an application.
Task 1: Creating a Console-Based Application
To create a console-based application, Brad needs to perform the following steps:
1. Select StartÆAll ProgramsÆMicrosoft Visual Studio 2005ÆMicrosoft Visual
Studio 2005. The Start Page - Microsoft Visual Studio window is displayed.
2. Select FileÆNewÆProject. The New Project dialog box will be displayed.
3. Select the project type as Visual C# from the Project types pane and Console
Application from the Templates pane.
4. Type the name of the new project as FunCityLand in the Name text box.
5. Specify the location where the new project is to be created as c:\chapter7\Activity2
in the Location combo box.
6. Click the OK button.
7. Open the Solution Explorer window and right-click the Program.cs file. The
shortcut menu is displayed.
8. Select the Rename option and type the new name as Distance.cs.
9. Double-click the Distance.cs file in the Solution Explorer window. The code view
of Distance.cs file is displayed.
Activity: Overloading an Operator
¤NIIT Polymorphism 7.25
10. Replace the existing code with the following code:
using System;
namespace FunCityLand

{
class Distance
{
internal int Length;
public Distance()
{
Length = 0;
}
public static Distance operator +(Distance Distance1, int
Value)
{
Distance1.Length += Value;
return Distance1;
}
public void DisplayDistance(Distance Distance2, int Length)
{
Distance Result;
Console.WriteLine("The distance travelled is {0}",
Distance2.Length);
Console.WriteLine("The remaining distance to reach the
destination is {0}", Length);
Result = Distance2 + Length;
Console.WriteLine("The total distance you have to
travel is {0}", Result.Length);
}
}
class EntryPoint
{
public static void Main()
{

Distance Distance1 = new Distance();
Distance Distance2 = new Distance();
string Location;
int TravelledDistance;
Console.WriteLine("Enter the Location you have reached:
A, B, C ");
Location = Console.ReadLine().ToUpper();
if (Location == "A" || Location == "B" || Location ==
"C")
{
Console.WriteLine("Enter the distance you have
covered: ");
TravelledDistance =
Convert.ToInt32(Console.ReadLine());
Distance2.Length = TravelledDistance;
switch (Location)
{
case "A":
Distance1.DisplayDistance(Distance2, 15);

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×