Chapter 4: Methods and Polymorphism


Polymorphism sounds like a disease old people are tested for every year. However, you probably surmise that polymorphism has something to do with object-oriented programming rather than medicine. Polymorphism means that something has the ability to appear in many shapes ”and that something is a method of an object- oriented programming language. In this case, a shape is the behavior that method performs . In this chapter, you ll learn about polymorphism and how to use it in an object-oriented program.

Methods

Let s begin our trek into the world of polymorphism with a look back at methods. You might wonder why we begin with a review of methods. We do so because you implement polymorphism in your program by defining two or more methods (more on this in the next section).

You learned in Chapter 2 that a method definition defines a behavior of an object. For example, the method Display() has the behavior of displaying student information. Student is the object. You define a method by specifying the method name , an argument list (if any), the body of the method, and a return value (if any).

The name of the method is used to call the method from a statement in a program, and the argument list contains data needed for the method to perform its behavior. Collectively, the name of the method and its argument are called the method s signature .

The body of the method contains one or more statements that execute when the method is called. This is where the behavior is actually performed. The return value is the value returned to the program after the method finishes completing its behavior. Some methods don t require an argument list or return value.

Polymorphism

Polymorphism technically means that one thing has the ability to take many shapes, as you learned in the introduction to this chapter. In programming terms, the thing is the name of a method and the shape is the behavior performed by the method. Therefore, polymorphism in programming terms means that the name of a method can have many behaviors.

Confused? Then you re in good company. The concept of polymorphism confuses many programmers, but the confusion usually goes away as soon as you see an example of polymorphism in action.

A real-world example of polymorphism is an on/off switch. Everyone is familiar with the concept of an on/off switch, what it does, and how to operate one. They realize that to start or activate something, you turn it on, and to stop or deactivate it, you turn it off. In other words, it works as a sort of toggle. However, the reality is that, internally, the on/of switch for your house lights is dramatically different from the on/off switch for your computer. Polymorphism in this case involves two same-named items (on/off switches) performing the same task (turning something on or off), despite being very different internally.

Let s return to the StudentInfo Java application from Chapter 3 and modify it to illustrate polymorphism. As you ll recall, the application defines two classes: the Student class and the GradStudent class, as shown here:

 class Student 
{
public void Write(int ID, int Grad, String Fname, String Lname) {
m_ID = ID;
m_Graduation = Grad;
m_First = Fname;
m_Last = Lname;
}
public void Display(){
System.out.println( "Student: " + m_ID + " " + m_First + " " +
m_Last + " Graduated: " + m_Graduation);
}
private int m_ID, m_Graduation;
private String m_First;
private String m_Last;
} class GradStudent extends Student
{
public void Write(int ID, int Grad, String Fname, String Lname, int yrGrad, String unSch, String major) {
super.Write(ID, Fname, Lname, Grad);
m_UndergradSchool = unSch;
m_Major = major;
YearGraduated = yrGrad;
}
public void Display(){
super.Display();
System.out.println(" Graduated: " + m_Graduation + " " +
m_UndergradSchool + " " + m_Major + " " + YearGraduated);
}
private YearGraduated;
private String m_UndergradSchool;
private String m_Major;
}

Each has the member methods Write() and Display() . The Write() method assigns values to instance variables of each class. The Display() method displays those values. Though not specifically noted in Chapter 3, each of these classes was actually designed with polymorphism already in mind. Each class contains methods named Display() and Write() that perform similar tasks , but are done differently. This is polymorphism in action.

Imagine if different names were used for the Display() method in each class, such as StudentDisplay() and GradDisplay() . A programmer who wanted to use these classes would need to memorize the name of each method for each object. This can easily become a challenge, especially if each class has many methods.

Programmers avoid any head scratching over methods and method signatures by performing a little polymorphism magic. They define a method in each class, with the same name, that performs a similar behavior. This requires the programmer to remember one name that is associated with a behavior. The sample classes ( Student and GradStudent ) each have their own Display() method.

Figure 4-1 is the Java application class definition of the next program, which shows polymorphism at work. The main() method in Figure 4-1 is practically the same as the main() method of the Java StudentInfo application in Chapter 3. However, there are a few minor modifications.

click to expand
Figure 4-1: The Display() method in this program is an example of polymorphism.

The first two statements create instances of the Student class and the GradStudent class. The Write() method for each instance is then called to assign values passed as parameters to attributes of the instance.

Polymorphism is used in the last two statements in this example. Both statements call the Display() method. However, because the student object is an instance of the Student class, the Student class s Display() method is called, and because the grad object is an instance of the GradStudent class, the GradStudent class s Display() method is called. Note how the two lines are nearly identical, except for the instances of their classes.

This is polymorphism at work ”one thing (the Display() method) has different shapes (behaviors, depending on the objects used to call the method). The same can be said about the Write() method because both classes define a Write() method.

Here is the complete Java application that illustrates polymorphism. The application declares an instance of the GradStudent class and then calls the Write() method to write information about a graduate student to instance variables of the Student class and the GradStudent class. The Display() method is then called to display instance variables on the screen.

 class StudentInfo { 
public static void main (String args[]) {
GradStudent myStudent = new GradStudent();
myStudent.Write(10, 1,"Bob","Smith", 2000,"Columbia University",
"CS");
myStudent.Display();
}
}
class Student
{
public void Write(int ID, int Grad, String Fname, String Lname) {
m_ID = ID;
m_Graduation = Grad;
m_First = Fname;
m_Last = Lname;
}
public void Display(){
System.out.println( "Student: " + m_ID + " " + m_First + " " + m_Last
+ " Graduated: " + m_Graduation);
}
private int m_ID, m_Graduation;
private String m_First;
private String m_Last;
}

class GradStudent extends Student
{
public void Write(int ID, int Grad, String Fname, String Lname,
int yrGrad, String unSch, String major) {
super.Write(ID, Fname, Lname, Grad);
m_UndergradSchool = unSch;
m_Major = major;
YearGraduated = yrGrad;
}
public void Display(){
super.Display();
System.out.println(" Graduated: " + m_Graduation + " " +
m_UndergradSchool + " " + m_Major + " " + YearGraduated);
}
private YearGraduated;
private String m_UndergradSchool;
private String m_Major;
}

Overloading Methods

Overloading is another one of those terms you hear used in conjunction with polymorphism. It means that two or more methods are defined using the same name, but with different argument lists. Overloading methods provides us with a way to define similar behavior to work with different types of data by writing a version of a method for each data type that is used.

Any variation in the argument list makes a method distinct from other methods of the same name. That is, the number of arguments, the data type of arguments, and the order in which arguments appear are considered different argument lists.

Let s say that you want to display attributes of the Student class and attributes of the GradStudent class. You could define two methods called Display() that are not associated with either class. One of these methods requires an instance of the Student class as its argument. The other method requires an instance of the GradStudent class as its argument. The second definition of the Display() method is said to overload the first definition of the Display() method.

The programmer simply calls the Display() method and passes it either the instance of the Student class or the instance of the GradStudent class. The compiler determines which version of Display() to use by the object passed to the Display() method.

The following example defines two versions of the Display() method. The first version requires an instance of the Student class as its argument list. The second version requires an instance of the GradStudent class. Each version calls the instance s Display() method to display attributes of the instance.

 public static void Display( Student s ) { 
s.Display();
}
public static void Display( GradStudent g ) {
g.Display();
}

Because these examples might be found in the StudentApp class (not Student or GradStudent ), we may opt to make them static . By making them static, we indicate that the methods can work on their own and that we don t need to declare a StudentApp object to use them.

Polymorphism Using C++

The previous example uses Java to illustrate polymorphism. Polymorphism can also be implemented using C++, which is shown in the next example. This C++ program defines a Student class and a GradStudent class. The GradStudent class inherits the Student class.

Both class definitions define a Write() member function and a Display() member function, similar to the previous Java program. The Write() member function assigns values of its argument list to attributes of the class. The Display() member function displays those attributes on the screen.

The Student class contains attributes that are common to all students: a student ID, the student name, and an indication of whether the student has graduated. The GradStudent class has attributes that pertain to a graduate student. These are the name of the student s undergraduate school, the year the student received an undergraduate degree, and the student s undergraduate major. The GradStudent class also can access protected attributes of the Student class because the GradStudent class inherits the Student class.

As with the Java example, the GradStudent class s Display method calls the Student base class s Display method to reuse code. Also, the signatures of the Display method in Student and GradStudent are identical.

The main() function contains the actual C++ program, which is practically the same program as the main() method in the Java example. The first two statements declare an instance of the Student class and the GradStudent class. The next two statements use those instances to call the Write() method of each instance, passing it information about students. The last two statements call the Display() function for the respective classes. Also, as with the Java program, the compiler uses the appropriate function for the given class.

Here is the output of the following program:

ID: 100

First: Harry

Last: Kim

Graduation: 2008

ID: 101

First: Elizabeth

Last: Jones

Graduation: 2008

Major: Comp Sci

Undergrad school: Columbia

Undergrad graduation: 2002

 #include <iostream> 
#include <string.h>
using namespace std;
class Student
{
protected:
int m_Graduation, m_ID;
char m_First[16], m_Last[16];
public:
void Display()
{
cout << "ID: " << m_ID << endl;
cout << "First: " << m_First << endl;
cout << "Last: " << m_Last << endl;
cout << "Graduation: " << m_Graduation << endl;
}
void Write( int ID, char First[], char Last[], int Graduation )
{
m_ID = ID;
strcpy( m_First, First );
strcpy( m_Last, Last );
m_Graduation = Graduation;
}
Student()
{
m_ID = m_Graduation = 0;
m_First[0] = m_Last[0] = '
 #include < iostream > 
#include <string.h>
using namespace std;
class Student
{
protected:
int m_Graduation, m_ID;
char m_First[16], m_Last[16];
public:
void Display()
{
cout << "ID: " << m_ID << endl;
cout << "First: " << m_First << endl;
cout << "Last: " << m_Last << endl;
cout << "Graduation: " << m_Graduation << endl;
}
void Write( int ID, char First[], char Last[], int Graduation )
{
m_ID = ID;
strcpy ( m_First, First );
strcpy( m_Last, Last );
m_Graduation = Graduation;
}
Student()
{
m_ID = m_Graduation = 0;
m_First[0] = m_Last[0] = '\0';
}
};

class GradStudent : public Student
{
protected:
int m_UndergradGraduation;
char m_UndergradSchool[64];
char m_Major[64];
public:
GradStudent()
{
m_UndergradGraduation=0;
m_UndergradSchool[0] = m_Major[0] = '\0';
}
void Write( int ID, char First[], char Last[], int Graduation,
char Major[], char UndergradSchool[], int UndergradGraduation )
{
Student::Write( ID, First, Last, Graduation );
strcpy( m_Major, Major );
strcpy( m_UndergradSchool, UndergradSchool );
m_UndergradGraduation = UndergradGraduation;
}
void Display()
{
Student::Display();
cout << "Major: " << m_Major << endl;
cout << "Undergrad school: " << m_UndergradSchool << endl;
cout << "Undergrad graduation: " << m_UndergradGraduation <<
endl;
}
};


int main()
{
Student student;
GradStudent gradStudent;
student.Write( 100, "Harry", "Kim", 2008 );
gradStudent.Write( 101, "Elizabeth", "Jones", 2008, "Comp Sci",
"Columbia", 2002 );
student.Display();
gradStudent.Display();
return 0;
}
';
}
};

class GradStudent : public Student
{
protected:
int m_UndergradGraduation;
char m_UndergradSchool[64];
char m_Major[64];
public:
GradStudent()
{
m_UndergradGraduation=0;
m_UndergradSchool[0] = m_Major[0] = '
 #include < iostream > 
#include <string.h>
using namespace std;
class Student
{
protected:
int m_Graduation, m_ID;
char m_First[16], m_Last[16];
public:
void Display()
{
cout << "ID: " << m_ID << endl;
cout << "First: " << m_First << endl;
cout << "Last: " << m_Last << endl;
cout << "Graduation: " << m_Graduation << endl;
}
void Write( int ID, char First[], char Last[], int Graduation )
{
m_ID = ID;
strcpy ( m_First, First );
strcpy( m_Last, Last );
m_Graduation = Graduation;
}
Student()
{
m_ID = m_Graduation = 0;
m_First[0] = m_Last[0] = '\0';
}
};

class GradStudent : public Student
{
protected:
int m_UndergradGraduation;
char m_UndergradSchool[64];
char m_Major[64];
public:
GradStudent()
{
m_UndergradGraduation=0;
m_UndergradSchool[0] = m_Major[0] = '\0';
}
void Write( int ID, char First[], char Last[], int Graduation,
char Major[], char UndergradSchool[], int UndergradGraduation )
{
Student::Write( ID, First, Last, Graduation );
strcpy( m_Major, Major );
strcpy( m_UndergradSchool, UndergradSchool );
m_UndergradGraduation = UndergradGraduation;
}
void Display()
{
Student::Display();
cout << "Major: " << m_Major << endl;
cout << "Undergrad school: " << m_UndergradSchool << endl;
cout << "Undergrad graduation: " << m_UndergradGraduation <<
endl;
}
};


int main()
{
Student student;
GradStudent gradStudent;
student.Write( 100, "Harry", "Kim", 2008 );
gradStudent.Write( 101, "Elizabeth", "Jones", 2008, "Comp Sci",
"Columbia", 2002 );
student.Display();
gradStudent.Display();
return 0;
}
';
}
void Write( int ID, char First[], char Last[], int Graduation,
char Major[], char UndergradSchool[], int UndergradGraduation )
{
Student::Write( ID, First, Last, Graduation );
strcpy( m_Major, Major );
strcpy( m_UndergradSchool, UndergradSchool );
m_UndergradGraduation = UndergradGraduation;
}
void Display()
{
Student::Display();
cout << "Major: " << m_Major << endl;
cout << "Undergrad school: " << m_UndergradSchool << endl;
cout << "Undergrad graduation: " << m_UndergradGraduation <<
endl;
}
};


int main()
{
Student student;
GradStudent gradStudent;
student.Write( 100, "Harry", "Kim", 2008 );
gradStudent.Write( 101, "Elizabeth", "Jones", 2008, "Comp Sci",
"Columbia", 2002 );
student.Display();
gradStudent.Display();
return 0;
}

An important benefit of polymorphism is that it gives programmers the ability to develop interfaces for complex applications. You ve probably heard the term interface used in connection with Application Programming Interface (API), which you use to build applications. An API consists of classes and methods used to perform complex behaviors within your program. You simply invoke appropriate classes and methods within your program to perform corresponding behaviors, and you don t have to worry about how those behaviors are actually performed because the API takes care of that for you.




OOP Demystified
OOP Demystified
ISBN: 0072253630
EAN: 2147483647
Year: 2006
Pages: 130

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net