This post is part of a series aimed at bringing people up to speed in what’s going on today in application development. 

Let’s move to Polymorphism.  Polymorphism is the one that always gave me trouble when I was learning OOP because it sounds a hell of a lot more complicated than it is at root, but also because there is just so much to polymorphism once you get deeper and deeper into OOP.  At root, polymorphism means that one thing can have many shapes (or, in World of Warcraft, Polymorph is where a mage turns you into a sheep).  From Wikipedia:

polymorphism is behavior that varies depending on the class in which the behavior is invoked. For example, the result of bark() for a Dog would differ from the result of bark() for a Jackal; and in a more sophisticated animal-emulation program, bark() would differ for a Chihuahua and a Saint Bernard.

 

This definition is a little incomplete in my opinion.  I am going to borrow a line from Raymond Lewallen (who did a great series on the 4 principles of OOP a while back) where he says that while polymorphism can be coupled with inheritance (as is implied by the wikipedia definition above) it does not require inheritance.  You can see polymorphism at work in one class in the form of overloading.  You can see polymorphism at work when implementing interfaces (covered later) that allows you to treat one object type like another if they share common interfaces.  You can see polymorphism at work in inheritance via overriding inherited behaviors.  Generics available in C# 2.0 are a type of polymorphism at work (called parametric polymorphism).  A lot of that is way beyond the scope here.  I only want to discuss overloading and overriding here, because those are the least complicated and the most often encountered when you first begin OOP and this is just an overview article.  Polymorphism is one of those things that you can talk about for days and still not see the end of.  Because of the many places you can see it at work, it’s one of the hardest parts of OO to define, and to fully understand, until you see it from all its different sides.

Overloading is a type of polymorphism (sometimes called ad-hoc polymorphism) where you essentially have multiple functions that perform the same task, return the same thing, and have the same name.  They differ in the number and/or type of arguments passed in.  Some will say that method overloading is not polymorphism.  Others will say it is.  I’m not here to deal in academics.  In the real world, overloaded behavior is considered to be polymorphic behavior, at least in the sense that from the perspective of the consumer of the API it’s polymorphic, but maybe in the perspective of the author it’s just syntactic sugar for multiple methods.  Overloading is important to understand and is a key feature of OOP, and I’m putting it under polymorphism.  Deal.  If you know enough about it to argue with me about whether or not it goes here…this post ain’t for you bub. :P

One of the places you most often see overloading in action is in the constructor of a class.  Take the following:

public class Person
{
     private int age;
     private string name;

     public Person()
     {}
 
     public Person(int theAge, string theName)
     {
          age = theAge;
          name = theName;
     }
 
    public Person(int birthYear)
   {
       age = thisyear – birthyear;
    }
}

In this case, we have a Person class.  We could create a new Person() with no arguments and set properties later.  Depending on the needs of our system though, we may want to create a person and pre-populate the age and name all at once.  To accomplish this, we overload the constructor to take two arguments, name and age.  We still are creating and returning an instance of Person, we just want to provide a little more info up front.  This is an overload.  It has the same name, but a different form (polymorph).  We may have another overload where we provide a year and calculate the age from that.  Whatever.

Outside of a constructor, you may overload other methods that do the same thing but might take different arguments.  Take a simple data access example.  Let’s say you want to provide a method to query a table and return a dataset.  At root, you may have

public DataSet QueryTable(string tableName)
{
     //query tablename with Select * from tableName
}

Now let’s say you want to provide a way to query a table and order the results.  You could create a whole new function called QueryTableWithOrderedResults, or you could overload the QueryTable function like this:

public DataSet QueryTable(string tableName, string orderBy)
{
     //still query and return a dataset, just this time add an Order By
}

Is this functionally different than creating a new method altogether?  Not really.  But it keeps your API clean, and it is widely used.  You will see it all the time in Visual Studio when using .net framework libraries where you have one function and multiple argument configurations you can pass in.  It’s there to make your life easier.

Overriding is a type of polymorphism that deals with changing pre-defined behaviors.  This is usually seen in terms of inheritance, where you may inherit a behavior from a base class, but want to alter that behavior in some way.

Let’s look at a real example from Winforms development.  In this post Chris Frazier has implemented a GradientPanel control (because for some reason it’s not a default thing).  He wants a panel that will have a gradient fill for a background rather than a single color.  If you look at his code, you see public class GradientPanel : Panel.  That’s our tip that his GradientPanel is a Panel.  A panel is already defined and handled by .net, and has a lot of behaviors that you wouldn’t want to replicate just to change one behavior, i.e. how the background fill is handled.  Now the problem is that Chris needs to replace the default behavior (fill with one color) with his desired behavior (fill with a gradient).  To do this he has to override the default behavior, in this case, the OnPaint function that comes from Panel. 

In every language the syntax to override default behavior is different, but the concept is the same.  You override the method with the same name, and same method signature (return type, arguments), but make it do something different.  That’s the fundamental difference between an overload and an override.  In an overload you change the arguments but keep the behavior the same.  In a override you keep the arguments the same but change the behavior.  If you look at his sample, he overrides the OnPaint, adds his behavior (creating the brushes and colors), and then passes control back to the base function.  This isn’t always necessary when overriding, it depends on what you are trying to accomplish.  In this case he wants the .net panel stuff to get handled too so that he doesn’t have to replicate it.  Here he is adding behavior to existing behavior.  However, in another scenario, you might want to replace existing behavior with your own.  In this case, you wouldn’t pass off control to the base class’s overridden function. 

The reason this works is because inheritance forms a type of contract with the calling code.  Because a GradientPanel is a Panel, whatever is calling the code knows that either way, there’s an OnPaint.  It’s either implicitly inherited or explicitly overridden, but one way or the other it’s getting executed.  That’s the polymorphism.  Regardless of the form (GradientPanel or Panel) you’re going to get a OnPaint.  The idea of a “contract” specifying expected definitions (but not necessarily implementations) of behavior is taken a step further when you talk about Interfaces, but that’s a story for a different day.

So, long story short, polymorphism is the principle of having one thing take many forms, or perform many behaviors, depending on context.  In theory it’s that simple.  In practice, there’s a lot of different ways you can use polymorphism, and I’ve only covered 2.  I am certain that I don’t even fully understand all the different types and methods of polymorphism, and that’s one of the great things about this field…there’s always something new to learn.


Tags: