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.

No comments:

Post a Comment