Friday, 27 November 2015

Gambas with Class

The simple principle of "code re-use" is an easy way of reducing project development time and improving the quality of your software.

It is clear that using existing code snippets will save you time by avoiding the task of "re-inventing the wheel".

And if you also keep a personal store of code that you have previously designed and tested, this should help improve the quality of your software projects.

You can store example code as snippets, complete routines, or even build modules to contain related functions. But possibly the most powerful option is to build classes.

An introduction to Classes

Do you find yourself re-writing the same basic code? Here is an example that may look familiar to you:-

    hFile = Open strFilePath For Read
    Do While Not Eof(hFile)
      Read #hFile, strTemp, -4096
      strData = strData & strTemp
    Close #hFile

This simple code snippet opens a text file and reads the contents into a variable: strData

Rather than type this into your code whenever you want to open and read a text file, you could create a function which you can copy & paste between projects or even put it in a module. Or you could consider creating a class.

When a class is included in your project, you can create instances of this class (i.e. create objects) and use any method or properties of this new object. So lets open the Gambas IDE, start a new project and create a new class file. Let's call it: ClsFile.

' Gambas class: ClsFile
'read & write absolute file path

Property PathFile As String        'declare a class property

Private strCFile As String        'a class variable

Private Sub PathFile_Write(Value As String) 'a class write function
  strCFile = Value

Private Function PathFile_Read() As String    'a class read function
  Return strCFile

Notice that the code in this class is Private. The only bit that is exposed (visible from the outside) is the Property: PathFile.

This is a working class, so go to the project Main form and create some test code by adding 2 buttons: use button text "write file name" and "read file name"

In the Main form code window, add this declaration:-

Public thisFile As New ClsFile

In the button code for the "write file name" button, add a line as shown below. Notice that as you start typing "thisFile" you should see the Gambas IDE prompt "thisFile"

...with the option of a single property: PathFile

Public Sub Button1_Click()
'the Write File Name button

Now add a line of code under the other button ("read file name"):-

Public Sub Button2_Click()
'the Read File Name button
  Me.Text = thisFile.PathFile

Now you should be able to run your project and set the file name using "write file name" and read it with "read file name"

Code Review

OK, so this class does not do anything useful at the moment, but it is worth studying the class and the test code to fully appreciate how it works.

The class code is encapsulated, exposing only the Property PathFile. The read and write functions are also hidden from the user of the class, so that the user only has to set the property or get the property.

In the main project code, the declaration:-

Public thisFile As New ClsFile

...creates an instance of the class, so that you can use this new object (thisFile) and use whatever functionality is provided.

Note that you can create as many objects from this class as you like, they will all be individuals, not copies of each other. So:-

Public thisFile As New ClsFile

Public thatFile As New ClsFile

Public theOtherFile As New ClsFile

...would reference 3 different files (e.g. /home/steve/file1, file2, file3).

Adding more functionality

We want to check whether a path + file name actually exists, so add this to the ClsFile:-

'read only property File Exists
Property Read FileExists As Boolean
Private bCFileExists As Boolean

Private Function FileExists_Read() As Boolean
  bCFileExists = Exist(strCFile, False)
  Return bCFileExists

...and add this to the project test code:-

Public Sub Button2_Click()
'the Read File Name button
  If thisFile.FileExists Then
     Me.Background = Color.Green
    Me.Background = Color.Red


...and play around with this to make sure it works.
Hint: you may need to create a real "testfile" in your file structure.

Read & Write

We need to be able to read the file contents and write new or modified text back to the file. Normally we would use class methods to open and close the file, but I want to take a simple approach and treat the file contents as just another class Property.

Add to ClsFile:-

Property FileText As String    'property available to class user

Private strCFileText As String

Private Function FileText_Read() As String
  strCFileText = ReadTextFile()
  Return strCFileText

Private Sub FileText_Write(Value As String)
  strCFileText = Value

Private Function ReadTextFile() As String
'read file and return contents
Dim hFile As File    
Dim strTemp As String   'read short chunks of the file
Dim strData As String   'build contents of file from each chunk
    hFile = Open strCFile For Read
    Do While Not Eof(hFile)
      Read #hFile, strTemp, -4096
      strData = strData & strTemp
    Close #hFile
    Return strData
  Return "error"

Private Function SaveFile() As Boolean
'save strText To file specified In strFilePath 
Dim hFile As File
Dim strTemp As String
    hFile = Open strCFile For Create
    Write #hFile, strCFileText, Len(strCFileText)
    Close #hFile
    Return True   
  Return False

Note that the 2 functions above are Private to this class, and that they take care of opening, reading, writing and closing the file. But the user of this class just sees the read/write Property: FileText

You can now modify the test code (also add a TextArea) and use this new property like this:-

TextArea1.Text = thisFile.FileText read the file, and:-

thisFile.FileText = TextArea1.Text write text back to the file, replacing the original contents.

For completeness, I'll add a method to delete the file.

Add to class:-

Public Function Delete() As Boolean
'returns true if successful, else false if no file or error 
  If FileExists_Read() = True Then
    Kill strCFile
    Return True
  Return False

Now you can use this class method in your test code something like this:-

Public Sub Button8_Click()
'file DELETE button
  If thisFile.Delete() Then
    TextArea1.Text = "File deleted"
    TextArea1.Text = "could not delete file"


Clearly this simple class example is no match for the FileSystemObject in Visual Basic, but it offers a surprising amount of functionality, including:-

  • Check whether a file exists: set Property FilePath, then get Property FileExists
  • Read a file: set Property FilePath, then get Property FileText
  • Write to a file: set Property FilePath, then set Property FileText
  • Edit a file: combination of get/set Property FileText
  • Create a text file: just set FilePath Property to a fully qualified path/file name, and set FileText to a string value (or "" for a blank file).
  • Copy a file: get FileText, change Property FilePath, set FileText
  • Delete a file: set Property FilePath, then use Method Delete
  • Move a file: combination of Copy and Delete

Once you have thoroughly tested your class, you will be able to use it with confidence whenever you create a new project that requires this kind of functionality.

There, that wasn't too painful was it?  And I didn't mention Object Orientated Programming once ...Oops!

No comments:

Post a Comment