Programmer to ProgrammerTM | |||||
|
|
|
|
|
|
|
|
|
|
|
| |||||||||||||||||||
The ASPToday
Article June 27, 2001 |
Previous
article - June 26, 2001 |
Next
article - June 28, 2001 | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
ABSTRACT |
| ||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
Article Discussion | Rate this article | Related Links | Index Entries | ||||||||
ARTICLE |
Now that Visual Basic is fully object-oriented, you should know more about object-oriented programming (OOP) in VB.NET. Kaushal Sanghavi has discussed OOP in VB.NET in general in the article published by ASPToday on 18 May 2001 (http://www.asptoday.com/content/articles/20010518.asp). The article, among others, introduced the three principles of OOP: encapsulation, inheritance and polymorphism. This article looks at polymorphism much closer. This article begins by giving the definitions of polymorphism in general and strictly in the OOP world. Understanding the term is crucial, as the word beginner OOP programmers often misunderstand polymorphism. It then continues with the use of polymorphism in OOP and why it is so important. Finally, the article shows polymorphism in action with a Windows application example called WhatAmI .
Indeed, polymorphism (literally means "many forms") is probably the most misunderstood term in OOP because the word has more than a few meanings. For example, if you type in the word polymorphism as a search keyword in an Internet search engine, you will find out that this word is also used in biology! In software engineering, however, discussions about polymorphism should start with the classification of polymorphism. Otherwise, we would be talking about definitions without knowing which polymorphism we were talking about. In modern software engineering discipline, polymorphism is classified into universal polymorphism and ad-hoc polymorphism. Universal polymorphism is considered more pure than ad-hoc polymorphism and is also called "true polymorphism". Ad-hoc polymorphism is often described as "apparent polymorphism". Universal polymorphism is subdivided into parametric polymorphism and inclusion polymorphism; and ad-hoc polymorphism can be subdivided into overloading and coercion. The four types of polymorphism are explained below.
This classification was put forward by Luca Cardelli (AT&T Bell Laboratories) and Peter Wegner (Brown University) in their paper which was published in Computing Surveys in December 1985 edition. The paper is titled On Understanding Types, Data Abstraction and Polymorphism and if you are interested to know more you can download the paper from http://research.microsoft.com/Users/luca/Papers/OnUnderstanding.pdf?WROXEMPTOKEN=1076407ZPXqWsFnX8FdlD0YhDf. This is the presently accepted definition of polymorphism by the software engineering community. In the olden world, however, when C Strachey first identified it in 1967, there were only two types of polymorphism: parametric polymorphism and ad-hoc polymorphism.
In OOP, however, when we talk about polymorphism, it simply means one interface with many implementations. To be more specific, the term is used to describe reference variables that may at run-time refer to objects of different classes. Overloading is also a type of polymorphism, however in OOP it is simply referred to as method overloading.
Polymorphism, inheritance and encapsulation are the three most important principles in object-oriented programming. Therefore, polymorphism plays a significant role. To see why, consider the three VB.NET classes in Figure 1: Employee, Manager and Programmer . The code for the classes and the main module that creates the classes is given in Listing 1.
Figure 1: The hierarchy of Employee, Manager and Programmer
Listing 1: Demonstrating polymorphism in VB.NET
Class Employee Protected Dim FirstName as String Protected Dim LastName as String Protected Dim CompanyName as String Public Sub New() CompanyName = "BrainySoftware.com" End Sub Public Overridable Sub Work System.Console.WriteLine( "I work at " & CompanyName ) System.Console.WriteLine( "I am a happy employee." ) End Sub End Class Class Manager : Inherits Employee Public Function Count(i as Integer, j as Integer) As Integer Count = i + j End Function Public Overrides Sub Work System.Console.WriteLine( "I work at " & CompanyName ) System.Console.WriteLine( "I am a proud manager" ) End Sub End Class Class Programmer : Inherits Employee Public Overrides Sub Work System.Console.WriteLine( "I work at " & CompanyName ) System.Console.WriteLine( "I like coding" ) End Sub End Class Module ModMain Sub Main() Dim AnEmployee as Employee AnEmployee = New Employee AnEmployee.Work AnEmployee = New Manager AnEmployee.Work End Sub End Module
The code in Listing 1 has a base class named Employee, which is the parent class of the other two: Programmer and Manager . The class Employee has three protected String variables and one subroutine called Work, which simply outputs a string that says: " I work at BrainySoftware.com. I am a happy employee ". However, this Sub is overriden in both Programmer and Manager . In the class Manager, the Work Sub will output a different string: " I work at BrainySoftware.com. I am a proud manager ". In the class Programmer, it will say: " I work at BrainySoftware.com. I like coding. "
The interesting part is given in the Sub Main of the main module. It starts by dimensioning a variable called AnEmployee of type Employee .
Dim AnEmployee as Employee
Assigned to it is the new object Employee that gets instantiated using the New keyword.
AnEmployee = New Employee
The Work sub of the class Employee is then invoked.
AnEmployee.Work
Up to this point, everything looks normal. It's just a process of instantiating an object of type Employee and calling the object's method. However, the line afterward is pretty unusual.
AnEmployee = New Manager
The object variable AnEmployee is of type Employee, yet it is assigned another object of type Manager. How come? Wouldn't it raise a compile error because of incompatible type? No, this is polymorphism. Polymorphism says a reference variable may at run-time refer to an object of a different class. In this case, a reference variable of type Employee may refer to an object of type Manager . However, not every type of object can be assigned to AnEmployee, but only objects of type Employee and objects whose classes are derived from Employee . So, if you compile and run the program, you will see the following message in the output screen.
I work at BrainySoftware.com
I am a happy employee
I work at BrainySoftware.com
I am a proud manager
Another interesting point is this. When AnEmployee is assigned an object of type Manager and its Work sub is invoked, it runs the Work method of Manager, not the Work of Employee . You can see from the console, the third and the fourth lines of the output clearly show that it is the Work sub of the class Manager that was invoked. Now that AnEmployee runs the Work sub of the class Manager, it must be a Manager, right? Wrong. If you don't believe, add the following line of code to the end of the sub Main .
System.Console.WriteLine( AnEmployee.Count(3, 4) )
So, the sub Main now looks like the following.
Sub Main() Dim AnEmployee as Employee AnEmployee = New Employee AnEmployee.Work AnEmployee = New Manager AnEmployee.Work System.Console.WriteLine( AnEmployee.Count(3, 4) ) End Sub
When you try to compile it, the VB compiler will complain: error BC30456: The name 'Count' is not a member of 'Employee' . So now AnEmployee is still an Employee . The last line in the sub Main, however, tries to run the Count function that only exists in Manager (apparently, only managers in BrainySoftware.com can count). What's important is this proves that AnEmployee is still an Employee . Being an Employee, it does not know how to count.
After seeing the code in Listing 1 and learning how polymorphism works, you probably wonder when you ever need it. You will find you need it in many types of applications. Sometimes polymorphism happens without you realizing it. The following example shows a more visual example of polymorphism.
When I first learned Visual Basic many years back from now, VB was the only easy Windows application development builder at that time. I remember how the controls in the Toolbox amazed me. It was very easy to create a control. Just drag and drop any control from the Toolbox to the form to add it. You then can change its properties in the Properties window. Up to now, the Properties window is still here. You can check a control's property values from this window. However, the following application shows you how to display a control's property values simply by clicking the control. Not a complex application, but it offers another polymorphism at work.
The application is called What Am I? It is simple. You have a screen (which is a Label control that is used to display some text) and a couple of controls from the toolbox. For the sake of simplicity, I chose only controls that can trigger an event when it is clicked. When you click a control, the property values and other information of that control will be displayed in the screen. (see Figure 2). The application is given in Listing 2, and can be downloaded at the bottom of this article. The application was written using Visual Studio.NET beta 1, that you can download from http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml&WROXEMPTOKEN=1076407ZPXqWsFnX8FdlD0YhDf if you are an MSDN subscriber.
Figure 2: The "What Am I" Game
The form in Figure 2 displays some information about the Button1 control. It shows the type of the control, the left and top coordinates plus the width and height of the control, and other information. When you click the Checkbox the information about the check box will be displayed.
Listing 2: The code for the "What Am I" Game
Imports System.ComponentModel Imports System.Drawing Imports System.WinForms Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " 'Required by the Windows Form Designer Private components As System.ComponentModel.Container Private WithEvents Label1 As System.WinForms.Label Private WithEvents CheckBox1 As System.WinForms.CheckBox Private WithEvents PictureBox1 As System.WinForms.PictureBox Private WithEvents LinkLabel1 As System.WinForms.LinkLabel Private WithEvents Screen As System.WinForms.Label Private WithEvents Button1 As System.WinForms.Button Dim WithEvents Form1 As System.WinForms.Form 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() Me.Screen = New System.WinForms.Label() Me.Button1 = New System.WinForms.Button() Me.LinkLabel1 = New System.WinForms.LinkLabel() Me.CheckBox1 = New System.WinForms.CheckBox() Me.Label1 = New System.WinForms.Label() Me.PictureBox1 = New System.WinForms.PictureBox() '@design Me.TrayHeight = 0 '@design Me.TrayLargeIcon = False '@design Me.TrayAutoArrange = True Screen.Location = New System.Drawing.Point(8, 8) Screen.Text = "Click one of the controls and I'll tell you what it is." Screen.Size = New System.Drawing.Size(496, 168) Screen.BorderStyle = System.WinForms.BorderStyle.Fixed3D Screen.TabIndex = 7 Screen.BackColor = System.Drawing.SystemColors.Window Button1.Location = New System.Drawing.Point(208, 208) Button1.Size = New System.Drawing.Size(72, 48) Button1.TabIndex = 1 Button1.Text = "Button1" LinkLabel1.Text = "LinkLabel1" LinkLabel1.Size = New System.Drawing.Size(96, 32) LinkLabel1.TabIndex = 3 LinkLabel1.TabStop = True LinkLabel1.Location = New System.Drawing.Point(96, 224) CheckBox1.Location = New System.Drawing.Point(320, 224) CheckBox1.Text = "CheckBox1" CheckBox1.Size = New System.Drawing.Size(88, 24) CheckBox1.TabIndex = 5 Label1.Location = New System.Drawing.Point(432, 216) Label1.Text = "Label1" Label1.Size = New System.Drawing.Size(72, 24) Label1.TabIndex = 8 PictureBox1.BorderStyle = System.WinForms.BorderStyle.FixedSingle PictureBox1.Location = New System.Drawing.Point(8, 200) PictureBox1.Size = New System.Drawing.Size(72, 56) PictureBox1.TabIndex = 4 PictureBox1.TabStop = False Me.Text = "Form1" Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(520, 273) Me.Controls.Add(Label1) Me.Controls.Add(CheckBox1) Me.Controls.Add(PictureBox1) Me.Controls.Add(LinkLabel1) Me.Controls.Add(Screen) Me.Controls.Add(Button1) End Sub #End Region Protected Sub CheckBox1_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) WhatAmI(CheckBox1) End Sub Protected Sub Label1_Click(ByVal sender As Object, ByVal e As System.EventArgs) WhatAmI(Label1) End Sub Protected Sub PictureBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) WhatAmI(PictureBox1) End Sub Protected Sub LinkLabel1_LinkClick(ByVal sender As Object, ByVal e As System.EventArgs) WhatAmI(LinkLabel1) End Sub Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) WhatAmI(Button1) End Sub Public Sub WhatAmI(ByVal control As Control) Screen.Text() = "I got clicked. Here are my statistics" & Chr(10) & _ "Type: " & control.GetType.ToString & Chr(10) & _ "Text: " & control.Text & chr(10) & _ "Top coordinate: " & control.Top & Chr(10) & _ "Height: " & control.Height & Chr(10) & _ "Left coordinate: " & control.Left & Chr(10) & _ "Width: " & control.Width & Chr(10) & _ "Parent: " & control.Parent.Text & Chr(10) & _ "Internal Information: " & control.ToString() End Sub End Class
How does this happen? To understand, first let's analyze the origins of the controls.
Every control is indirectly derived from System.WinForms.Control . A button ( System.WinForms.Button), for instance, is a child class of System.WinForms.ButtonBase, which is a child class of System.WinForms.RichControl, which in turn is derived from System.WinForms.Control . (See Figure 3)
Figure 3: The hierarchy for class System.WinForms.Button and System.WinForms.CheckBox
Control RichControl BaseButton Button
Control RichControl BaseButton CheckBox
And so are labels, picture boxes, check boxes and other controls. They are indirectly derived from System.WinForms.Control . Now, let's see the polymorphism part of this program.
Each control has a line of code in its Click or CheckedChanged event procedure. The code is simply a call to the WhatAmI function and each control passes itself to this function. Therefore, the CheckBox1 checkbox passes CheckBox1 to the WhatAmI function, and from Button1, the function is called by passing Button1 as the argument. The form has five sample controls: CheckBox1, Label1, LinkLabel1, PictureBox1 and Button1. Here is the code for that part.
Protected Sub CheckBox1_CheckedChanged(ByVal sender As Object, _
ByVal e As System.EventArgs)
WhatAmI(CheckBox1)
End Sub
Protected Sub Label1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
WhatAmI(Label1)
End Sub
Protected Sub PictureBox1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
WhatAmI(PictureBox1)
End Sub
Protected Sub LinkLabel1_LinkClick(ByVal sender As Object, _
ByVal e As System.EventArgs)
WhatAmI(LinkLabel1)
End Sub
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
WhatAmI(Button1)
End Sub
Now, let's have a look at the WhatAmI sub.
Public Sub WhatAmI(ByVal control As Control)
Screen.Text() = _
"I got clicked. Here are my statistics" & Chr(10) & _
"Type: " & control.GetType.ToString & Chr(10) & _
"Text: " & control.Text & chr(10) & _
"Top coordinate: " & control.Top & Chr(10) & _
"Height: " & control.Height & Chr(10) & _
"Left coordinate: " & control.Left & Chr(10) & _
"Width: " & control.Width & Chr(10) & _
"Parent: " & control.Parent.Text & Chr(10) & _
"Internal Information: " & control.ToString()
End Sub
It accepts one argument of type Control . However, when I click a control, I am passing that control to the sub, and yet there is no error message raised. Why? Thanks to polymorphism. Since buttons, labels, link labels, checkboxes, picture boxes and others are indirectly derived from Control, you can pass them to the WhatAmI sub and let polymorphism quietly work on them.
Once the control is accepted, it does not matter what is being passed to the Sub. You can query its many properties and other methods, such as the GetType (to obtain the type of the control, i.e. a button, a label, or some other) and ToString methods. The result will be different, depending on which control you are passing. Again, this is polymorphism in action.
Polymorphism in object-oriented programming languages is the ability to assign to an object reference an object of a different type, as long as the different type is directly or indirectly derived from the type of the object reference. Because the main benefit of OOP is code reuse, polymorphism (as well as inheritance and encapsulation) is very common. The article showed you the many possible meanings of polymorphism and what it really means in OOP. It also demonstrated how polymorphism worked in VB.NET with two examples. Download the code. It's now your turn to do some polymorphism.
Links:
1. Click here to download the paper On Understanding Types, Data Abstraction and Polymorphism: http://research.microsoft.com/Users/luca/Papers/OnUnderstanding.pdf?WROXEMPTOKEN=1076407ZPXqWsFnX8FdlD0YhDf
2. Click here to get the list of polymorphism-related papers: http://citeseer.nj.nec.com/cardelli85understanding.html
3. Click here to download .NET Framework: http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml
4. Click here to download Visual Studio.NET: http://msdn.microsoft.com/vstudio/nextgen/default.asp?WROXEMPTOKEN=1076407ZPXqWsFnX8FdlD0YhDf
|
| |||||||
| |||||||||||||||
|
ASPToday is brought to you by
Wrox Press (http://www.wrox.com/). Please see our terms
and conditions and privacy
policy. ASPToday is optimised for Microsoft Internet Explorer 5 browsers. Please report any website problems to webmaster@asptoday.com. Copyright © 2001 Wrox Press. All Rights Reserved. |