JAL Computing

C++COMProgramming .NET Mac Palm CPP/CLI Hobbies

 

Home
Up

Chapter 37 "Polymorphism"

Well, I approach this chapter with trepidation as I find very little agreement on the meaning of polymorphism or the related terms, interface and type. I know when I see a polymorphic solution, but it is hard to define.

From "Webster's 7th New Collegiate Dictionary" we get: polymorphic : having, assuming, or occurring in various forms, characters or styles.

From "Object-Oriented Software Construction, 2nd ed.", Bertrand Meyer we get: Polymorphism means the ability to take several forms.

From WikiBooks we get: "The concept of polymorphism is wider. Polymorphism exists every time we use two methods that have the same signature, but differ in the implementation."

From GPWiki we get: "Polymorphism is the idea that different classes can have different implementation of the same function."

From C2 we get : "Same interface, different implementation. Substitutability."

From Chapter 1 we get: "polymorphism provides runtime variations in program behavior"

From "Object Oriented Analysis and Design, 2nd. ed." , Grady Booch we get: "polymorphism; it represents a concept in type theory in which a single name (such as a variable declaration) may denote objects of many different classes that are related by some common superclass."

Note: According to Grady Booch, the litmus test is "The existence of a switch statement that selects an action based upon the type of an object is often a warning sign that the developer has failed to apply polymorphic behavior effectively." Here is the dastardly switch on type method:

        static void DastardlySwitchPolymorphism(IDrawable d)
        {
            if (d is Circle)
            {
                ((Circle)d).Draw();
            }
            else if (d is Square)
            {
                ((Square)d).Draw();
            }
            else if (d is Oval)
            {
                ((Oval)d).Draw();
            }
            else
            {
                // awk!
                throw new ArgumentException();
            }
        }

The twisted programmer's polymorphic version is extensible.

        
	static void RunTimePolymorphism(IDrawable d)
        {
            d.Draw();
            System.Console.WriteLine(d.GetType());  // eg. outputs Polymorphism.Circle
        }

Finally, here is the definition of polymorphism from of the Gang of Four. 

From "Design Patterns", Gamma, Helm, Johnson, Vlissides we get for Polymorphism: The ability to substitute objects of matching interface for one another at runtime.

In "Design Patterns" a type is defined as: "The set of all signatures defined by an object's operations is called the interface to the object...  A type is a name used to denote a particular interface.... An object may have many types, and widely different objects can share a type.... An object's interface says nothing about its implementation--different objects are free to implement requests differently."

Note: It is unfortunate that the definition of type from "Design Patterns" uses the term interface which has a specific meaning in the C# language. However, this definition pre dates the C# language. In this chapter, I have tried to color code the word interface to represent the C# use of this term. Rather than try to rewrite history, I have decided to stick to the historical definition of type used by a group of pioneers in object oriented programming. I understand that this may add confusion to the subject, but I feel that this is the right thing to do. More importantly, it recognizes that the definition of polymorphism outside of C#  relies on this classic definition of interface.

One common theme to all definitions of polymorphism is the ability to take or assume several forms. Another theme is same interface, same function, same signature different implementation. Another theme is the ability to substitute different objects with the same matching interface at runtime. If one defines a type as a name for a particular interface, then polymorphism involves programming to a type, such that the implementation details can be different and are discoverable at runtime. Each class that implements the type can provide a different implementation of the type. When programming to a type, the caller does not know the class of the object, only that the object implements the type of interest. The actual implementation is discovered and invoked at runtime.

Again, I am going to stick out my neck and suggest that polymorphic behavior can be implemented in C# using interfaces, Subclassing and Delegates. All three idioms can be used to declare a type. In the case of a Delegate, the type is defined as the signature of a single method call, similar to an interface with only a single method declaration. Interfaces, abstract classes and Delegates allow the twisted programmer to program to a type so that the actual implementation is not known at compile time. Instead the actual implementation is discovered at runtime, providing runtime variation in behavior. 

The definition of polymorphism at its lowest common denominator is: the ability to take or assume several forms.

The "Readers Digest" definition of polymorphism is: same interface, same function, same signature different implementation.

The twisted definition of runtime polymorphism is: Runtime polymorphism involves programming to a type, such that the implementation details can be different and are discoverable at runtime. When programming to a type, the caller does not know the class of the object, only that the object implements the type of interest. 

The twisted definition of inheritance (subclassing) polymorphism is: Inheritance polymorphism is a special form of runtime polymorphism in which polymorphic behavior is implemented through inheritance. The class of the object that implements the call is discoverable at runtime. In C#, inheritance polymorphism can be implemented using interfaces, abstract classes or overriding virtual methods in a base class. Implementing an interface in C#  is considered to be analogous to inheriting from a pure virtual class in C++. 

Delegates vs Interfaces

According to MSDN: "Both delegates and interfaces allow a class designer to separate type declarations and implementation. A given interface can be inherited and implemented by any class or struct; a delegate can created for a method on any class, as long as the method fits the method signature for the delegate. An interface reference or a delegate can be used by an object with no knowledge of the class that implements the interface or delegate method."

Interfaces vs  C Function Pointers

C programmers may have a better insight into delegates as function pointers to polymorphic methods. The C standard library qsort algorithm uses function pointers to implement a qsort algorithm. The qsort algorithm does not provide any implementation of the compare function, only a function prototype. The user of the qsort must provide a "compare" function that matches the function prototype. In C# this can be accomplished using the IComparer interface. We can see the similarity between using interfaces, C function pointers and C# delegates to invoke methods that can have more than one form (polymorphism).

Note: As is evident, C function pointers can be used to implement polymorphic behavior in C, a language which does not support, out of the box, classes or inheritance! In fact, the twisted coder is not surprised at all by the power of the function pointer. Objective languages can be written in C. In fact, inheritance and overriding of virtual functions can be implemented with v_tables filled with pointers to functions.

Compile Time Polymorphism vs Runtime Polymorphism

In inheritance polymorphism the implementation is discovered at runtime. The twisted coder may ask "What is compile time polymorphism?" According to Scott Meyers in "Effective C++ 2nd. ed." the answer is C++ templates.

Note: Here is the short version of templates from "The C++ Standard Library" Nicolai M. Josuttis: "Templates are functions or classes that are written for one or more types not yet specified. When you use a template, you pass the types as arguments, explicitly or implicitly."

According to Meyers, you can best use templates when you can substitute different types without affecting the behavior of the template class. He gives as an example a stack class. So a linked list implementation of a stack can work with many different types without affecting the behavior of the stack class. However, an instance of a template stack class is implemented with a specific type at compile time.

Litmus Test

Well, the real litmus test of an idea is that the idea abstracts out a concept that is useful to the twisted coder. When the twisted coder recognizes a problem that requires runtime polymorphism, he/she can ask if the polymorphic behavior is best implemented using interfaces, abstract classes/subclassing or delegates/events. Each approach has advantages and disadvantages. The twisted coder can use the "tool" that best fits the problem at hand.

Hope that helps.

- 30 -

 

Send mail to [email protected] with questions or comments about this web site. Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 © 
Last modified: 08/04/09
Hosted by www.Geocities.ws

1