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
    Loop
    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
End

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


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
   thisFile.PathFile="/home/steve/testfile"
End



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
End


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
End


...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
  Else
    Me.Background = Color.Red
  Endif

End


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

Private Sub FileText_Write(Value As String)
  strCFileText = Value
  SaveFile()
End


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
    Loop
    Close #hFile
    Return strData
Catch
  Return "error"
End

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   
Catch
  Return False
End


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

...to read the file, and:-

thisFile.FileText = TextArea1.Text

...to 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
  Endif
Catch
  Return False
End


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"
  Else
    TextArea1.Text = "could not delete file"
  Endif
End


Conclusion


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