Demonstrating Polymorphic Behavior

Section 10.4 created a commission employee class hierarchy, in which class BasePlusCommissionEmployee inherited from class CommissionEmployee. The examples in that section manipulated CommissionEmployee and BasePlusCommissionEmployee objects by using references to them to invoke their methods. We aimed base class references at base class objects and derived class references at derived class objects. These assignments are natural and straightforwardbase class references are intended to refer to base class objects, and derived class references are intended to refer to derived class objects. However, other assignments are possible.

In the next example, we aim a base class reference at a derived class object. We then show how invoking a method on a derived class object via a base class reference invokes the derived class functionalitythe type of the actual referenced object, not the type of the reference, determines which method is called. This example demonstrates the key concept that an object of a derived class can be treated as an object of its base class. This enables various interesting manipulations. An application can create an array of base class references that refer to objects of many derived class types. This is allowed because each derived class object is an object of its base class. For instance, we can assign the reference of a BasePlusCommissionEmployee object to a base class CommissionEmployee variable because a BasePlusCommissionEmployee is a CommissionEmployeeso we can treat a BasePlusCommissionEmployee as a CommissionEmployee.

A base class object is not an object of any of its derived classes. For example, we cannot assign the reference of a CommissionEmployee object to a derived class BasePlusCommissionEmployee variable because a CommissionEmployee is not a BasePlusCommissionEmployeea CommissionEmployee does not, for example, have a baseSalary instance variable and does not have a BaseSalary property. The is-a relationship applies from a derived class to its direct and indirect base classes, but not vice versa.

It turns out that the compiler does allow the assignment of a base class reference to a derived class variable if we explicitly cast the base class reference to the derived class typea technique we discuss in greater detail in Section 11.5.6. Why would we ever want to perform such an assignment? A base class reference can be used to invoke only the methods declared in the base classattempting to invoke derived-class-only methods through a base class reference results in compilation errors. If an application needs to perform a derived-class-specific operation on a derived class object referenced by a base class variable, the application must first cast the base class reference to a derived class reference through a technique known as downcasting. This enables the application to invoke derived class methods that are not in the base class. We present a concrete example of downcasting in Section 11.5.6.

The example in Fig. 11.1 demonstrates three ways to use base class and derived class variables to store references to base class and derived class objects. The first two are straightforwardas in Section 10.4, we assign a base class reference to a base class variable, and we assign a derived class reference to a derived class variable. Then we demonstrate the relationship between derived classes and base classes (i.e., the is-a relationship) by assigning a derived class reference to a base class variable. [Note: This application uses classes CommissionEmployee3 and BasePlusCommissionEmployee4 from Fig. 10.13 and Fig. 10.14, respectively.]

Figure 11.1. Assigning base class and derived class references to base class and derived class variables.

(This item is displayed on pages 513 - 514 in the print version)

 1 // Fig. 11.1: PolymorphismTest.cs
 2 // Assigning base class and derived class references to base class and
 3 // derived class variables.
 4 using System;
 5
 6 public class PolymorphismTest
 7 {
 8 public static void Main( string[] args )
 9 {
10 // assign base class reference to base class variable
11 CommissionEmployee3 commissionEmployee = new CommissionEmployee3(
12  "Sue", "Jones", "222-22-2222", 10000.00M, .06M ); 
13
14 // assign derived class reference to derived class variable
15 BasePlusCommissionEmployee4 basePlusCommissionEmployee =
16  new BasePlusCommissionEmployee4( "Bob", "Lewis", 
17  "333-33-3333", 5000.00M, .04M, 300.00M ); 
18
19 // invoke ToString and Earnings on base class object
20 // using base class variable
21 Console.WriteLine( "{0} {1}:

{2}
{3}: {4:C}
",
22 "Call CommissionEmployee3's ToString with base class reference",
23 "to base class object", commissionEmployee.ToString(),
24 "earnings", commissionEmployee.Earnings() );
25
26 // invoke ToString and Earnings on derived class object
27 // using derived class variable
28 Console.WriteLine( "{0} {1}:

{2}
{3}: {4:C}
",
29 "Call BasePlusCommissionEmployee4's ToString with derived class",
30 "reference to derived class object",
31 basePlusCommissionEmployee.ToString(),
32 "earnings", basePlusCommissionEmployee.Earnings() );
33
34 // invoke ToString and Earnings on derived class object
35 // using base class variable
36 CommissionEmployee3 commissionEmployee2 =
37  basePlusCommissionEmployee; 
38 Console.WriteLine( "{0} {1}:

{2}
{3}: {4:C}",
39 "Call BasePlusCommissionEmployee4's ToString with base class",
40 "reference to derived class object",
41 commissionEmployee2.ToString(), "earnings",
42 commissionEmployee2.Earnings() );
43 } // end Main
44 } // end class PolymorphismTest
 
Call CommissionEmployee3's ToString with base class reference to base class
object:

commission employee: Sue Jones
social security number: 222-22-2222
gross sales: $10,000.00
commission rate: 0.06
earnings: $600.00

Call BasePlusCommissionEmployee4's ToString with derived class reference to
derived class object:

base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $300.00
earnings: $500.00

Call BasePlusCommissionEmployee4's ToString with base class reference to de-
rived class object:

base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $300.00
earnings: $500.00

In Fig. 11.1, lines 1112 create a new CommissionEmployee3 object and assign its reference to a CommissionEmployee3 variable. Lines 1517 create a new BasePlusCommissionEmployee4 object and assign its reference to a BasePlusCommissionEmployee4 variable. These assignments are naturalfor example, a CommissionEmployee3 variable's primary purpose is to hold a reference to a CommissionEmployee3 object. Lines 2124 use the reference commissionEmployee to invoke methods ToString and Earnings. Because commissionEmployee refers to a CommissionEmployee3 object, base class CommissionEmployee3's version of the methods are called. Similarly, lines 2832 use basePlusCommissionEmployee to invoke the methods ToString and Earnings on the BasePlusCommissionEmployee4 object. This invokes derived class BasePlusCommissionEmployee4's version of the methods.

Lines 3637 then assign the reference to derived class object basePlusCommissionEmployee to a base class CommissionEmployee3 variable, which lines 3842 use to invoke methods ToString and Earnings. A base class variable that contains a reference to a derived class object and is used to call a virtual method actually calls the overriding derived class version of the method. Hence, commissionEmployee2.ToString() in line 41 actually calls class BasePlusCommissionEmployee4's ToString method. The compiler allows this "crossover" because an object of a derived class is an object of its base class (but not vice versa). When the compiler encounters a method call made through a variable, the compiler determines if the method can be called by checking the variable's class type. If that class contains the proper method declaration (or inherits one), the compiler allows the call to be compiled. At execution time, the type of the object to which the variable refers determines the actual method to use.

Abstract Classes and Methods

Preface

Index

    Introduction to Computers, the Internet and Visual C#

    Introduction to the Visual C# 2005 Express Edition IDE

    Introduction to C# Applications

    Introduction to Classes and Objects

    Control Statements: Part 1

    Control Statements: Part 2

    Methods: A Deeper Look

    Arrays

    Classes and Objects: A Deeper Look

    Object-Oriented Programming: Inheritance

    Polymorphism, Interfaces & Operator Overloading

    Exception Handling

    Graphical User Interface Concepts: Part 1

    Graphical User Interface Concepts: Part 2

    Multithreading

    Strings, Characters and Regular Expressions

    Graphics and Multimedia

    Files and Streams

    Extensible Markup Language (XML)

    Database, SQL and ADO.NET

    ASP.NET 2.0, Web Forms and Web Controls

    Web Services

    Networking: Streams-Based Sockets and Datagrams

    Searching and Sorting

    Data Structures

    Generics

    Collections

    Appendix A. Operator Precedence Chart

    Appendix B. Number Systems

    Appendix C. Using the Visual Studio 2005 Debugger

    Appendix D. ASCII Character Set

    Appendix E. Unicode®

    Appendix F. Introduction to XHTML: Part 1

    Appendix G. Introduction to XHTML: Part 2

    Appendix H. HTML/XHTML Special Characters

    Appendix I. HTML/XHTML Colors

    Appendix J. ATM Case Study Code

    Appendix K. UML 2: Additional Diagram Types

    Appendix L. Simple Types

    Index



    Visual C# How to Program
    Visual C# 2005 How to Program (2nd Edition)
    ISBN: 0131525239
    EAN: 2147483647
    Year: 2004
    Pages: 600

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