Raymond Lewallen

Sponsors

The Lounge

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Polymorphism Defined

Finally, the final of the 4 posts on object-oriented principles for those of you just coming to .Net from non-OOP languages.  Data Abstraction, Encapsulation and Inheritance we have already discussed.  Now we will talk about polymorphism.

Polymorphism means one name, many forms.  Polymorphism manifests itself by having multiple methods all with the same name, but slighty different functionality.  Updated statement: Polymorphism can be coupled with inheritance, but inheritance is not a requirement to gain polymorphic behaviors.  Because of this, it can be difficult to fully grasp the full potential of polymorphism until you get some practice with it and see exactly what happens under different scenarios.  We’re only going to talk about polymorphism, like the other topics, at the basic level. 

There are 2 basic types of polymorphism.  Overridding, also called run-time polymorphism, and overloading, which is referred to as compile-time polymorphism.  This difference is, for method overloading, the compiler determines which method will be executed, and this decision is made when the code gets compiled. Which method will be used for method overriding is determined at runtime based on the dynamic type of an object.

Let’s look at some code:

' Base class for library assets

Public MustInherit Class LibraryAsset

 

    ' Default fine per day for overdue items

    Private Const _finePerDay As Double = 1.25

 

    ' Due date for an item that has been checked out

    Private _dueDate As DateTime

    Public Property DueDate() As DateTime

        Get

            Return _dueDate

        End Get

        Set(ByVal Value As DateTime)

            _dueDate = Value

        End Set

    End Property

 

    ' Calculates the default fine amount for an overdue item

    Public Overridable Function CalculateFineTotal() As Double

        Dim daysOverdue As Int32 = CalculateDaysOverdue()

        If daysOverdue > 0 Then

            Return daysOverdue * _finePerDay

        Else

            Return 0.0

        End If

    End Function

 

    ' Calculates how many days overdue for an item being returned

    Protected Function CalculateDaysOverdue() As Int32

        Return DateDiff(DateInterval.Day, _dueDate, DateTime.Now())

    End Function

 

End Class

 

' Magazine class that inherits LibraryAsset

Public NotInheritable Class Magazine

    Inherits LibraryAsset

 

End Class

 

' Book class that inherits LibraryAsset

Public NotInheritable Class Book

    Inherits LibraryAsset

 

    ' This is morphing the CalculateFineTotal() function of the base class.

    ' This function overrides the base class function, and any call

    '   to CalculateFineTotal from any instantiated Book class will

    '   use this function, not the base class function.

    ' This type of polymorphism is called overriding.

    Public Overrides Function CalculateFineTotal() As Double

        Dim daysOverdue As Int32 = CalculateDaysOverdue()

        If daysOverdue > 0 Then

            Return daysOverdue * 0.75

        Else

            Return 0.0

        End If

    End Function

 

End Class

 

' AudioCassette class that inherits LibraryAsset

Public NotInheritable Class AudioCassette

    Inherits LibraryAsset

 

    ' This is morphing the CalculateFineTotal() function of the base class.

    ' This is morphing the CalculateFineTotal(double) function of the

    '   audiocassette class.

    ' This function overrides the base class function, and any call

    '   to CalculateFineTotal() from any instantiated AudioCassette

    '   Class will use this function, not the base class function.

    ' This type of polymorphism is called overloading and overriding.

    Public Overloads Overrides Function CalculateFineTotal() As Double

        Dim daysOverdue As Int32 = CalculateDaysOverdue()

        If daysOverdue > 0 Then

            Return daysOverdue * 0.25

        Else

            Return 0.0

        End If

    End Function

 

    ' This is morphing the CalculateFineTotal() function of the

    '   audiocassette class.

    ' This type of polymorphism is called overloading.

    Public Overloads Function CalculateFineTotal(ByVal finePerDay As Double) As Double

        Dim daysOverdue As Int32 = CalculateDaysOverdue()

        If daysOverdue > 0 AndAlso finePerDay > 0.0 Then

            Return daysOverdue * finePerDay

        Else

            Return 0.0

        End If

    End Function

End Class

 

You see our library asset class.  Pay attention to the overridable function CalculateFineTotal().  In LibraryAsset, we have defined the default functionality for this method that any derived classes can use.  Any class derived from LibraryAsset can use this default behavior and calculate fines based on the default implementation of $1.25 per day late.  This is true for our Magazine class.  We didn’t override the function so when late fees are calculated for late magazine returns, it will use the default implementation.

Now look at the book class.  We have overridden the CalculateFineTotal to use a different value when determining late fees.  The overrides keywork in VB tells the caller that any method call will use the virtual method found in Book, not the default implementation found in LibraryAsset.  We have implemented runtime polymorphism – method overriding.

Lets move on to AudioCassette.  Here we have the same method overriding we found in the book class.  Fines are calculated based on $0.25 per day.  Notice we’ve added something extra.  We’ve added the Overloads keywork to our function and to a new function with the same name, except the new function now accepts a parameter.  Now the caller can call either method, and depending on whether or not a parameter is passed, that determines with method will be executed.  Notice we do not include the overrides keywork in the 2nd function with a parameter.  This is because not method exists in LibraryAsset with that same signature (accepting a parameter of type double).  You can only override methods with the same signature in a base class.

Now lets look at some code that creates all these library items and checks them in and cacluates our fines based on returning them 3 days late:

Public Class Demo

 

    Public Sub Go()

        ' Set the due date to be three days ago

        Dim dueDate As DateTime = DateAdd(DateInterval.Day, -3, Now())

        ReturnMagazine(dueDate)

        ReturnBook(dueDate)

        ReturnAudioCassette(dueDate)

    End Sub

 

    Public Sub ReturnMagazine(ByVal dueDate As DateTime)

        Dim myMagazine As LibraryAsset = New Magazine

        myMagazine.DueDate = dueDate

        Dim amountDue As Double = myMagazine.CalculateFineTotal()

        Console.WriteLine("Magazine: {0}", amountDue.ToString())

    End Sub

 

    Public Sub ReturnBook(ByVal dueDate As DateTime)

        Dim myBook As LibraryAsset = New Book

        myBook.DueDate = dueDate

        Dim amountDue As Double = myBook.CalculateFineTotal()

        Console.WriteLine("Book: {0}", amountDue.ToString())

    End Sub

 

    Public Sub ReturnAudioCassette(ByVal dueDate As DateTime)

        Dim myAudioCassette As AudioCassette = New AudioCassette

        myAudioCassette.DueDate = dueDate

        Dim amountDue As Double

        amountDue = myAudioCassette.CalculateFineTotal()

        Console.WriteLine("AudioCassette1: {0}", amountDue.ToString())

        amountDue = myAudioCassette.CalculateFineTotal(3.0)

        Console.WriteLine("AudioCassette2: {0}", amountDue.ToString())

    End Sub

 

End Class

The output will look like the following:

Magazine: 3.75
Book: 2.25
AudioCassette1: 0.75
AudioCassette2: 9

You can see how all of our output was different, based on the method that was executed.  We created a new Magazine, which is a type of LibraryAsset.  That is why the instantiation says “myMagazine As LibraryAsset”.  However, since we actually want a magazine, we create a “New Magazine”.  Same thing with book.  For Book, its a little bit more tricky.  Since we created a Book of the type LibraryAsset, this is where the polymorphism comes into play.  Book overrides the CalculateFineTotal of LibraryAsset.  Audiocassette is a little bit different.  It actually extends the implementation of LibraryAsset by including an overloaded function for CalculateFineTotal().  If we weren’t going to use the function that took a parameter, we would create it the same way we created the Book and Magazine classes.  But in order to use the overloaded function, we have to create a new AudioCassette of the type AudioCassette, because LibraryAsset doesn’t support the overloaded function.

Only the Magazine used the default method found in the base class.  Book and AudioCassette used their own implementations of the method.  Also, at compile time, the decision was made which method would be used when we calculate amountDue for the AudioCassette class.  The first call used the 1st method in AudioCassette without parameters.  The 2nd call used the 2nd method with a parameter.

Currently listening to: Paul Revere - Beastie Boys


Posted Tue, Mar 15 2005 7:57 AM by Raymond Lewallen

[Advertisement]

Comments

Marius Gheorghe wrote re: Polymorphism Defined
on Wed, Mar 16 2005 12:38 AM
No offense intended....but the code is in Vb.NET and the comments are with red. Those 2 things are not exactly "invite" you to read the code. At least make the comments green....is way easier on the eye.
Again....no offense intended.
Raymond Lewallen wrote re: Polymorphism Defined
on Wed, Mar 16 2005 4:54 AM
I'll keep that in mind for future posts Marius. I may go in and change it. About 11 or 12 years ago when I starting using Visual FoxPro 3.0, the default comment color was red. It has stuck with me ever since. I always change my IDE to comment in red so its easier for me to see.
JavaKid wrote re: Polymorphism Defined
on Wed, Mar 16 2005 1:27 PM
What about polymorphism through Interfaces?

I see one biggest benefits of Polymorphism is the ability to take two or more unrelated objects and treat them as if they were of the same type... this can be achieved of course through the use of Interfaces.


JavaKid.
Raymond Lewallen wrote re: Polymorphism Defined
on Wed, Mar 16 2005 1:42 PM
Polymorphism via interfaces. Even though this existed in VB6 (the intelligent and insightful Daniel Moth and I discussed this awhile back) I did not want to cover it in this post. I wanted to discuss just the OO implementation principle alone and discuss the polymorphism via implementation inheritance. There are many aspects of polymorphism that have not been discussed in this post. This was intended to only hit the very basic, basic tip of the iceburg. In the near future, me, and I'm hoping a few others here at CB, will be undertaking the task of discussing all aspects of polymorphism via both interface and implementation inheritance. It is much too involved and complex to discuss all in one post. Understanding interfaces is the next step up from the basic level of understanding I have discussed here, and so will be in a future post by someone here at CodeBetter.
TrackBack wrote Polymorphism is not coupled to implementation inhe
on Wed, Mar 16 2005 3:49 PM
Polymorphism is not coupled to implementation inheritance
TrackBack wrote A few takes on polymorphism
on Wed, Mar 16 2005 6:00 PM
TrackBack wrote A few takes on polymorphism
on Wed, Mar 16 2005 6:05 PM
TrackBack wrote Polymorphism Defined (from: Raymond Lewallen)
on Wed, Mar 16 2005 8:14 PM
David Hayden wrote OOP and Design Pattern Resources
on Wed, Jan 18 2006 7:16 PM
 I received an email message via this blog for some help in identifying good recources on OOP and...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?