Wednesday, April 30, 2008

Polymorphism in Visual Basic

Ref: http://msdn2.microsoft.com/en-us/library/z9k8e08x.aspx

Polymorphism refers to the ability to define multiple classes with functionally different, yet identically named methods or properties that can be used interchangeably by client code at run time.

In This Section:
How Visual Basic Provides Polymorphism Illustrates different approaches to polymorphism.
Inheritance-Based Polymorphism Discusses using inheritance to achieve polymorphism.
Interface-Based Polymorphism Discusses using interfaces to achieve polymorphism.
How Visual Basic Provides Polymorphism?

Traditionally, polymorphism in Visual Basic was done by using interfaces, and interfaces can still be used for this purpose. However, now Visual Basic provides the option of using inheritance to provide polymorphism.

As with other issues in object-oriented programming, the option to use depends on your specific requirements. In general, use inheritance when you want to create baseline functionality that derived classes can extend; use interfaces when similar functionality has to be provided by multiple implementations that have little in common.

Most object-oriented programming systems provide polymorphism through inheritance. Inheritance-based polymorphism involves defining methods in a base class and overriding them with new implementations in derived classes.
For example, you could define a class, BaseTax, that provides baseline functionality for computing sales tax in a state. Classes derived from BaseTax, such as CountyTax or CityTax, could implement methods such as CalculateTax as appropriate.

Polymorphism comes from the fact that you could call the CalculateTax method of an object belonging to any class that derived from BaseTax, without knowing which class the object belonged to.

The TestPoly procedure in the following Visual Basic Code demonstrates inheritance-based polymorphism:

' %5.3 State tax
Const StateRate As Double = 0.053
' %2.8 City tax
Const CityRate As Double = 0.028
Public Class BaseTax
Overridable Function CalculateTax(ByVal Amount As Double) As Double
' Calculate state tax.
Return Amount * StateRate
End FunctionEnd Class

Public Class CityTax
' This method calls a method in the base class
' and modifies the returned value.
Inherits BaseTax
Private BaseAmount As Double
Overrides Function CalculateTax(ByVal Amount As Double) As Double
' Some cities apply a tax to the total cost of purchases,
' including other taxes.
BaseAmount = MyBase.CalculateTax(Amount)
Return CityRate * (BaseAmount + Amount) + BaseAmount
End FunctionEnd Class

Sub TestPoly()
Dim Item1 As New BaseTax
Dim Item2 As New CityTax ' $22.74 normal purchase.
ShowTax(Item1, 22.74) ' $22.74 city purchase.
ShowTax(Item2, 22.74)End Sub
Sub ShowTax(ByVal Item As BaseTax, ByVal SaleAmount As Double)
' Item is declared as BaseTax, but you can
' pass an item of type CityTax instead.
Dim TaxAmount As Double
TaxAmount = Item.CalculateTax(SaleAmount)
MsgBox("The tax is: " & Format(TaxAmount, "C"))
End Sub

In this example, the ShowTax procedure accepts a parameter named Item of type BaseTax, but you can also pass any of the classes derived from the BaseTax class, such as CityTax. The advantage of this design is that you can add new classes derived from the BaseTax class without changing the client code in the ShowTax procedure.

Interface-Based Polymorphism
Interfaces provide another way you can accomplish polymorphism in Visual Basic. Interfaces describe properties and methods like classes, but unlike classes, interfaces cannot provide any implementation. Multiple interfaces have the advantage of allowing systems of software components to evolve without breaking existing code.

To achieve polymorphism with interfaces, you implement an interface in different ways in several classes. Client applications can use either the old or the new implementations in exactly the same way.

The advantage to interface-based polymorphism is that you do not need to re-compile existing client applications to get them to work with new interface implementations.

The following example defines an interface named Shape2 that is implemented in a class named RightTriangleClass2 and RectangleClass2.
A procedure named ProcessShape2 calls the CalculateArea method of instances of RightTriangleClass2 or RectangleClass2:

Sub TestInterface()
Dim RectangleObject2 As New RectangleClass2
Dim RightTriangleObject2 As New RightTriangleClass2
ProcessShape2(RightTriangleObject2, 3, 14)
ProcessShape2(RectangleObject2, 3, 5)
End Sub

Sub ProcessShape2(ByVal Shape2 As Shape2, ByVal X As Double, ByVal Y As Double)
MsgBox("The area of the object is " & Shape2.CalculateArea(X, Y))End Sub
Public Interface Shape2
Function CalculateArea(ByVal X As Double, ByVal Y As Double) As Double
End Interface
Public Class RightTriangleClass2
Implements Shape2
Function CalculateArea(ByVal X As Double, ByVal Y As Double) As Double
Implements Shape2.CalculateArea ' Calculate the area of a right triangle.
Return 0.5 * (X * Y)
End Function
End Class

Public Class RectangleClass2
Implements Shape2
Function CalculateArea(ByVal X As Double, ByVal Y As Double) As Double
Implements Shape2.CalculateArea ' Calculate the area of a rectangle.
Return X * Y
End Function
End Class

Saturday, April 26, 2008

VB Object Oriented Programming

Reference: http://en.wikibooks.org/wiki/Programming:Visual_Basic_Classic/Object_Oriented_Programming

We will now move into a more advanced aspect of VB - OOP. But don't worry, Object Oriented Programming is quite simple, in fact it is probably simpler for those who have never programmed before than for those with long experience of traditional Fortran/Basic/Pascal (pick your favourite imperative language).

You should be familiar with VB's event-driven programming style by now. However I'll explain it again. When you're doing general VB programming, your thoughts should go in this pattern: "If the user does this, what should happen? How would I make it happen?" Then you would write the program to fit the answers to these questions. That is event-driven programming. You program according to what events the user would trigger. Dragging a picture, clicking a button, and typing a word are all events.

You, being the brave coder that you are, would ask: "WHY do I HAVE to think like that??"

Well here's an alternative way for you to think: Object Oriented Programming(OOP). In the world of OOP, you break a problem down into small parts and solve them individually. If you are to program in an object oriented style, you would think of every variable or functions as a property of an object, and everything would seem like an object to you. OOP is hard to explain so you'll have to experience it in the following examples.

Imagine that you have a bottle of juice. What properties does it have? What events does it have?(What can it do?) Here's a list I could think of:

 Private Colour As String  'What colour?
Private Fruit As String 'What kind of fruit?
Private Volume As Single 'How much?
Public Sub MakeJuice(c As String, f As String, v As Single) 'Make some
Colour = c
Fruit = f
Volume = v
End Sub

Public Sub Evaporate() 'Well, that's the only thing I could think of
Volume = Volume - 10
End Sub

Behold. That's our first class. Don't worry about anything right now. I will go over those later. Anyway, let's assume that this class is named, "Juice". Think of it as a general description of a bottle of juice. Now we can create an actual bottle of apple juice:

 Private AppleJuice As Juice  'Define
Set AppleJuice = New Juice 'Create a new instance of Juice
AppleJuice.MakeJuice "brown", "apple", 30

Watch:

 AppleJuice.Evaporate   '20 units left
AppleJuice.Evaporate '10 left
AppleJuice.Evaporate 'Yes!!

"Wait", you interrupted my rant once again, "but why do I have to use OOP? Just because you hate apple juice?"

OOP is good for large-scale programming - As your code grows large, there are going to be more and more procedures/functions to your program, and your code is going to be so cluttered that one more look at it, you'd scream. That is why I'm teaching you OOP! (So instead of looking at hundreds of scattered procedures/functions, you look at organized Objects.) s

User Defined Types

You can think of a type as a simple form of class. Types can only hold variables, not procedures/functions.

An important distinction between user defined types ('UDT') and and 'classes' in 'VB6' is that 'UDTs' are value types while 'classes' are reference types. This means that when you store an object ('instance' of a 'class') in a variable what actually happens is that a pointer to the existing object is stored but when you store a 'UDT' instance in a variable a copy of the instance is stored. For instance imagine that you have defind a class, 'Class1', and a UDT, 'Type1':

 Dim ac As Class1
Dim bc As Class1
Dim at As Type1
Dim bt As Type1

Now assign ac to bc:

 Set bc = ac

and at to bt

 bt = at

Now make a change to one of the properties of bc and look at the corresponding property in ac. You should see that when you change bc that ac also changes. This is because ac and bc are really pointers to the same block of memory. If you do the same exercise with bt and at you should see that changing properties of bt does not affect at. This is because at and bt are values not references and occupy distinct locations in memory.

This is important when storing objects in 'Collections'. If you add an object to a collection you can later change the values of its properties and the object in the collection will also seem to change. in fact it is the same object because what is stored in the collection is the reference ('pointer') to the object. However if you store a 'UDT' in a collection what is stored is a copy of the values not a reference so changing the original UDT will not affect the content of the Collection.

Classes

Classes are a combination of subroutines and types. By that I mean that when you write a class it looks very much like a type but is also contains subroutines and functions.

Each class in VB6 is a distinct file, there can only be one class in a file and the class cannot be spread out in several files; this is a feature of VB6 not a requirement of object oriented programming.

A class looks very much like an ordinary module but has the file extension .cls instead of .bas

Inheritance

There are two types of inheritance: implementation and interface. However Visual Basic Classic provides only Interface inheritance. Implementation inheritance can be simulated by a combination of interface inheritance and delegation.

One of the common ways to introduce inheritance is to show a program that creates dog and cat objects or car and train objects.

For example in Visual Basic we can declare two classes dog and cat like this:

Class cDog

 Option Explicit

Public Sub Sound()
Debug.Print "Woof"
End Sub

Class cCat

 Option Explicit

Public Sub Sound()
Debug.Print "Meow"
End Sub

module main

 Public Sub main()
Dim oDog as cDog
Dim oCat as cCat

Set oDog = New cDog
Set oCat = New cCat

oDog.Sound
oCat.Sound

End Sub

When you run this program it will print:

 Woof
Meow

Now this is all very well until you decide that you would like an array of pets:

 Dim aPets(1 to 10) as ????

Unless you declare the aPets array as variant you have to give it a type. One way is to create a class called cPet and use it instead of cDog and cCat:

Class cPet

 Option Explicit

Public IsDog as Boolean

Public Sub Sound()
If IsDog Then
Debug.Print "Woof"
Else
Debug.Print "Meow"
End If

End Sub

Now our main routine might look like this:

 Option Explicit

Dim aPet(1 to 10) as cPet

Public Sub main()

Dim lPet as Long

For lPet = 1 to 10
Set aPet(lPet) = New cPet
If lPet<=5 then
aPet(lPet).IsDog = True
Else
aPet(lPet).IsDog = False
End If
Next lPet

'Now find out what noise they make.
For lPet = 1 to 10
aPet(lPet).Sound
Next lPet

End Sub

This should print:

Woof
Woof
Woof
Woof
Woof
Meow
Meow
Meow
Meow
Meow

Look reasonable? For the reqirements so far revealed this works fine. But what happens when you discover that there are things that cats do that have no analogue in dogs? What about other kinds of pet? For example, you want your cat to purr. You can have a method called purr but where will you put it? It surely doesn't belong in cPet because dogs can't purr and neither can guinea pigs or fish.

The thing to do is to separate out those features that are common to all pets and create a class that deals only with those, we can rewrite cPet for this purpose. Now we can go back to our original cDog and cCat classes and modify them to inherit the 'interface from cPet.

Class cPet rewritten

 Option Explicit

Public Sub Sound()
End Sub

Notice that the Sound method is empty. this is because it exists only to define the interface. The interface is like the layout of the pins on a plug or socket; any plug that has the same layout, size and shape will plug in to a socket implementing the same interface. What goes on inside the thing you plug in is a separate issue; vacuum cleaners and television sets both use the same mains plug.

To make this work we must now modify cDog and cCat:

Class cDog

 Option Explicit
Implements cPet

Private Sub cPet_Sound()
Debug.Print "Woof"
End Sub

Class cCat

 Option Explicit
Implements cPet

Private Sub cPet_Sound()
Debug.Print "Meow"
End Sub

Public Sub Purr()
Debug.Print "Purr"
End Sub

Collections

In the pet examples above an array of cPet objects is used to hold the pets. This works well if you know exactly how many pets you have. But what happens if you adopt another stray puppy or your cat has kittens?

One solution is to use a Collection object instead of an array. A collection object looks a little like an array but lets you add and remove items without worrying about the declared size, it just expands and contracts automatically.