Visual Basic/Object Oriented Programming

From Wikibooks, open books for an open world
Jump to navigation Jump to search

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.)

Types[edit | edit source]

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 '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 defined 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[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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

Class cCat[edit | edit source]

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

module main[edit | edit source]

  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[edit | edit source]

  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 requirements 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[edit | edit source]

  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[edit | edit source]

  Option Explicit
  Implements cPet
  
  Private Sub cPet_Sound()
    Debug.Print "Woof"
  End Sub

Class cCat[edit | edit source]

  Option Explicit
  Implements cPet
  Private Sub cPet_Sound()
    Debug.Print "Meow"
  End Sub
  
  Public Sub Purr()
    Debug.Print "Purr"
  End Sub

Collections[edit | edit source]

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.

Iterators[edit | edit source]


Previous: External_Processes Contents Next: Effective Programming