[BASIC] Object-Oriented Programming

Creating Extension - Shared Libraries
Forum rules
For sharing working examples of macros / scripts. These can be in any script language supported by OpenOffice.org [Basic, Python, Netbean] or as source code files in Java or C# even - but requires the actual source code listing. This forum is not for asking questions about writing your own macros.

[BASIC] Object-Oriented Programming

Postby JPL » Sat Dec 15, 2012 1:19 pm

A well kept secret.

The definition in BASIC of class modules is possible exactly like in Visual Basic.
The sophistication level of those modules is comparable with that of VB6.
Next lines illustrate their features with a few examples.

How to proceed ?

Definition of a class :
Code: Select all   Expand viewCollapse view
Option Compatible
Option ClassModule

Option Explicit

REM -----------------------------------------------------------------------------------------------------------------------
REM --- Internal Variables                                                                           ---
REM -----------------------------------------------------------------------------------------------------------------------

Private _X      As Double
Private _Y      As Double

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CONSTRUCTORS / DESTRUCTORS                                                                    ---
REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Initialize()
'   Default point = Origin of axis
   _X = 0
   _Y = 0
End Sub      '   Constructor

REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Terminate()
   _X = - 4.94065645841247E-324      '   Most negative value allowed for Double variables
   _Y = - 4.94065645841247E-324
end sub

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS GET/LET/SET PROPERTIES                                                                 ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Property Get X As Double
   X = _X
End Property

Public Property Let X(ByVal pValue As Double)
   _X = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Y As Double
   Y = _Y
End Property

Public Property Let Y(ByVal pValue As Double)
   _Y = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Dummy As Variant
   Dummy = Null
End Property

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS METHODS                                                                              ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Sub Move(ByVal pX As Double, ByVal pY As Double)
   _X = _X + pX
   _Y = _Y + pY
End Sub

If one enters above code in a module called « Point » the name of the class will be also « Point ».

The statements « Option Compatible » and « Option ClassModule » heading the module determine the characteristic of the module, i.e. it is a class module. They must be present exactly in that order, otherwise the source will not pass the compilation.

A class module contains a number of Internal Variables. They are grouped before the following functions/subs and get usually the « Private » attribute. It means that the internal variable can be used only inside the module itself. « Public » meaning the opposite. Note however that this attribute is ignored in BASIC. The internal variables may be of any type, including another class. An example will be given below. It might also refer to a UNO object.

The Subs « Class_Initialize » and « Class_Terminate » are resp. the constructor and destructor of the class. The first one is executed before the first usage of a class instance, the second at its suppression (see below).

The properties are defined by the « Property Get », « Property Let » and « Property Set » routines. « Get » provides the value of the property, « Let » corresponds with a usual assignment, « Set » is there for assigning objects or complex structures to the property. Note that the value returned by « Property Get » and the argument of « Property Let » must have IDENTICAL TYPES.
Note also that the « Exit » statement gets an additional option « Exit Property ».

Methods are Subs or Functions. A Sub executes an arbitrary action and represents the most usual case of a method.

Usage of the « Point » class:

The declaration of a class instance is done by the « Dim » statement. The associated variable should be declared as an « Object ».
The « Set » statement creates the instance and executes the constructor.

Code: Select all   Expand viewCollapse view
   Dim a As Object
   Set a = New Point
   a.X = 4
   a.Y = 1
   MsgBox a._X

The code below is functionally equivalent to the previous one and is even more concise.
However one must understand that the constructor will only be executed when the execution will reach the first executable statement involving the variable « a », i.e. just before execution of the « a.X = 4 » statement. This means that for each statement between the variable declaration and its first use the interpreter will insert code to check if there is a need to trigger the constructor.
Therefore personally I will privilege the first shape.

Code: Select all   Expand viewCollapse view
   Dim a As New Point
   a.X = 4
   a.Y = 1
   MsgBox a._X


Definition of the « Circle » class:

Code: Select all   Expand viewCollapse view
Option Compatible
Option ClassModule

Option Explicit

REM -----------------------------------------------------------------------------------------------------------------------
REM --- Internal Variables                                                                        ---
REM -----------------------------------------------------------------------------------------------------------------------

Private _R      As Double
Private _Center   As Object

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CONSTRUCTORS / DESTRUCTORS                                                                    ---
REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Initialize()
'   Default circle = Null circle at axis origin
   _R = 0
   Set _Center = New Point
End Sub      '   Constructor

REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Terminate()
   _R = 0
   Erase _Center
End Sub

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS GET/LET/SET PROPERTIES                                                                 ---
REM -----------------------------------------------------------------------------------------------------------------------

Property Get R As Double
   R = _R
End Property

Public Property Let R(ByVal pValue As Double)
   _R = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Center As Object
   Set Center = _Center
End Property

Property Set Center(ByVal pValue As Object)
   Set _Center = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Function Area() As Double
   Area = PI() * R * R
End Function

Public Function Circumference() As Double
   Circumference = 2 * PI() * R
End Function

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Dummy As Variant
   Dummy = Null
End Property

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS METHODS                                                                              ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Sub MoveHoriz(ByVal pValue)      '   pValue might be negative
   _Center.Move(pValue, 0)
End Sub

Public Sub MoveVert(ByVal pValue)         '   pValue might be negative
   _Center.Move(0, pValue)
End Sub

REM -----------------------------------------------------------------------------------------------------------------------
Public Function IntersectX() As Variant
'   Return intersection points of circle with X-axis
'   Substitute y = 0 in circle equation (x-Cx)2 + (y-Cy)2 = R2
'      => Equation of degree 2 with unknown x
Dim a As Double, b As Double, c As Double, dDiscr As Double
   a = 1
   b = -2 * _Center.X
   c = (_Center.X ^ 2) + (_Center.Y ^ 2) - (R ^ 2)
   dDiscr = (b ^ 2) - (4 * a * c)

Dim oInterSect1 As Object, oInterSect2 As Object
   Select Case True
      Case dDiscr < 0      :   InterSectX = Array()
      Case dDiscr = 0
         Set oInterSect1 = New Point
         oInterSect.X = -b / (2 * a)
         Set InterSectX = Array(oInterSect)
      Case Else
         Set oInterSect1 = New Point
         Set oInterSect2 = New Point
         oInterSect1.X = (-b - Sqr(dDiscr)) / (2 * a)
         oInterSect2.X = (-b + Sqr(dDiscr)) / (2 * a)
         InterSectX = Array(oInterSect1, oInterSect2)
   End Select
End Function


Specificities :

One of the internal variables is an instance of class « Point ».

A function like « Area », beside the actions it potentially executes, returns additionally a value. What's the difference between « Property Get Area() » and « Public Function Area() » ? There is no difference except when the IDE debugger is involved. See below.

The destructor « Class_Terminate » contains an « Erase » statement which itself will activate the destructor of the « _Center » object which is of type « Point ».

The « MoveHoriz » and « MoveVert » methods invoke the « Move » method of the « Point » class to apply it on the internal « _Center » variable.

Examples :

- With illustration of the benefit of the « With » statement and of cascading properties in « b.Center.X » :

Code: Select all   Expand viewCollapse view
   Dim a As Object
   Set a = New Point
   a.X = 2
   a.Y = 1
   Dim b As Object
   Set b = New Circle
   With b
      .R = 2
      Set .Center = a
      .MoveHoriz(2)   '   Center becomes (4,1)
      MsgBox "Circle centered on (" & .Center.X & "," & .Center.Y & "). Circumference = " & .Circumference
   End With
   Erase b


- Next example uses the « IntersectX » method which returns an array of the « Points » which are at the intersection of an instance of type « Circle » and the X-axis : there can be 0, 1 or 2 such points.

Code: Select all   Expand viewCollapse view
   Dim b As Object
   Set b = New Circle
   b.Center.X = 4
   b.Center.Y = 1
   b.R = 2
   Dim vPoints As Variant, i As Integer
   vPoints = b.IntersectX()   '   Return an array of Points objects
   For i = LBound(vPoints) To UBound(vPoints)
      MsgBox vPoints(i).X
   Next i


Debugging :

Using Xray is useless. Indeed one can't get any useful information from that (moreover very useful) tool. However no other caveat.

The behaviour of the IDE debugger requires more attention. Either the execution is suspended inside the class. In this case the internal variables (and of course any other variable in scope) of the instance are visible as usually by naming them. Or the execution is outside the class. In that case the visualisation of a class instance will go through the computation by the debugger of each property of the class to find its value ! Really super, because even a property being itself a class instance will be displayed in a tree correctly.
However this means :
- that if the computation of the property contains an error, the debugger will make the same error. That's why it is sometimes very useful to use temporarily during the debugging a « Function » instead of « Property Get »;
- that if you are in the step-by-step mode, the step-by-step will enter, under the impulse of the debugger, into the execution of each « Property Get » routine ..., which will lead rapidly and irreversibly to a crash of AOO/LibO.

The « Dummy » property has been inserted in each class module because the debugger displays in the IDE all properties except strangely the last one ... ?

In conclusion : visualising a class variable, yes, but when the computation of the properties is error-free, and, after visualisation, remove any class variable from the watched variables before continuing the execution.

Other remarks :

Above examples work in all AOO/LibO listed in my signature.
Basic supports also the « Implements » verb like in VB6. Its usage however makes, in my opinion, not much sense.
VB6 accepts also in a class module the keyword « This » to designate the current instance in execution. Additionally it allows passing the current object as argument to a function external to the module. This seems not possible in BASIC, as far as I know.
Inheritance between object classes is not supported. Moreover the « Inherits » verb is implemented in VB only in versions later than VB6.

Hoping these explanations will be helpful ...
JPL
Last edited by JPL on Thu May 01, 2014 11:46 am, edited 2 times in total.
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby saleem145 » Mon Dec 24, 2012 5:06 pm

Is it possible to define a function that returns a Point?? And then call it from Calc??

Cell A1 = Function That returns Point

And Then call a function in another cell that gets a property.

Cell A2 = GetX(Cell A1)
OpenOffice 3.4.0
Mac OS X 10.5.8
saleem145
 
Posts: 130
Joined: Mon Jul 02, 2012 4:47 pm

Re: [BASIC] Object-Oriented Programming

Postby JPL » Mon Dec 24, 2012 6:00 pm

Is it possible to define a function that returns a Point??

The answer is Yes.
And then call it from Calc??
Cell A1 = Function That returns Point

The answer is No. I'm afraid functions called from Calc formulas must return values of one of the elementary types (string, numeric value, date, ...), not an object.

JPL.
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby JPL » Sun Feb 17, 2013 12:33 am

:alarm: LIBREOFFICE 4.0 :alarm:

The object orientation technique described above for Basic programs DOES NOT work as such in LibreOffice 4.0 anymore while it worked perfectly in the previous releases.
To have it still working replace in the examples (and in your own code ...) all occurrences of
Code: Select all   Expand viewCollapse view
Property Let

by
Code: Select all   Expand viewCollapse view
Property Set

A bug report has been posted in Bugzilla. See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=60752

As long as the bug is not corrected a way to have a code working both in AOO (all releases) and LO (all releases including 4.0) is to duplicate each Property Let routine with an identical Property Set one.

JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby JPL » Fri May 10, 2013 6:33 pm

The object orientation technique described above for Basic programs DOES NOT work as such in LibreOffice 4.0 anymore while it worked perfectly in the previous releases.


:D The bug has been corrected in LibreOffice as from version 4.0.2 :D

JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby JPL » Thu May 01, 2014 11:51 am

From the top post:
VB6 accepts also in a class module the keyword « This » to designate the current instance in execution. Additionally it allows passing the current object as argument to a function external to the module. This seems not possible in BASIC, as far as I know.

A workaround exists. Next construction is valid.

- in the class module define an internal variable
Code: Select all   Expand viewCollapse view
Private _This As Object

- in the module which creates the instance, write a 2nd statement after the New statement, like in next example:
Code: Select all   Expand viewCollapse view
Dim a As Object
Set a = New Point
Set a._This = a

- and, in the class module again, it is then possible to export the current instance to an external routine, like in
Code: Select all   Expand viewCollapse view
Call anExternalRoutine(_This, ...)

Hoping this will be helpful ...
JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby ahat » Sat Jun 14, 2014 8:00 am

Wouldn't this create an internal dependency of the object on itself so that the object will never be garbage collected? Would it be necessary to implement a "Release" method which will need to be called when done with the object to avoid memory leaks?

Code: Select all   Expand viewCollapse view
Sub Release()
    _This = Null
End Sub
LibreOffice 4.2.3.3 on Ubuntu 13.10
ahat
 
Posts: 2
Joined: Sat Jun 14, 2014 7:52 am

Re: [BASIC] Object-Oriented Programming

Postby JPL » Sat Jun 14, 2014 11:41 am

Would it be necessary to implement a "Release" method which will need to be called when done with the object to avoid memory leaks?

Good question !

First, I would prefer to use
Code: Select all   Expand viewCollapse view
Sub Release()
    Set _This = Nothing
End Sub

to avoid the risk you mention.
Anyway, my perception is that _This only contains a pointer to an object descriptor which contains the original object instance. Nullifying the pointer itself has no beneficial effect on the memory, in my mind.

Important is first to manage well the scope (Global, Public, ...) of his variables. I presume Basic drops unneeded memory when any variable reaches its end-of-life.
Additionally, indeed, having and using a "release", "dispose", or whatever method - defined in the class module itself - to clean up the instance is certainly to be considered.

Thanks.
JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby ahat » Sun Jun 15, 2014 3:57 am

I believe in the Basic internals assigning a pointer to an object increases an internal reference counter and assigning the pointer to Nothing decreases the counter. This way the garbarge collector knows when to garbage collect the obect.

Just as a test, I have put together the following:

clsTest
Code: Select all   Expand viewCollapse view
' clsTest
Option Compatible
Option ClassModule
Option Explicit

Public Name As String
Public _This As Object

Public Sub Release()
   Set _This = Nothing
End Sub

Private Sub Class_Terminate()
    MsgBox Name & ": Terminating"
End Sub


Test routine
Code: Select all   Expand viewCollapse view
Option Explicit

Sub Test

   Dim a As New clsTest
   Dim b As New clsTest
   
   a.Name = "a"
   b.Name = "b"
   Set a._This = a
   Set b._This = b
   
   a.Release()
   Set a = Nothing
   Set b = Nothing

End Sub


Running the test routine pops up "a: Terminating" only - so b is not garbage collected. Something to keep in mind perhaps.

Of course, it would be better for the VBA "Me" construct to be implemented.
LibreOffice 4.2.3.3 on Ubuntu 13.10
ahat
 
Posts: 2
Joined: Sat Jun 14, 2014 7:52 am

Re: [BASIC] Object-Oriented Programming

Postby martinbrait » Tue Mar 15, 2016 6:32 am

LibreOffice 3.6.2 on Windows7
martinbrait
 
Posts: 6
Joined: Fri Apr 26, 2013 9:15 am

Re: [BASIC] Object-Oriented Programming

Postby bawldiggle » Tue May 03, 2016 3:18 pm

Thank you for this "tute" on Classes :)
- this is my 4th post as an OpenOffice newbie
- I am still not sure if AOO modules and dialogs are classes or more akin to pre MS 2003 module sheets and Dialog sheets
- are OO Dialogs a Class or just a Dialog sheet ?

I have so much to learn to convert from VBA to BASIC
- the MS ribbon has driven me (and my grey haired customers) away from MS

IMHO to say LO/OO BASIC is like VBA ... is a very long stretch of the imagination.
- since migrating to this forum and AOO, in one day, I have learned more here than I did in 2 weeks "else where" ;)

BUT I am really struggling finding lists of objects, methods, properties, etc for BASIC
- a script editor with intellisence for BASIC would be very handy
    Win-7 HP x86 | Win-7 PRO x64 | Win-XP PRO x86
    Linux Mint (experimental)
User avatar
bawldiggle
 
Posts: 18
Joined: Sat Apr 09, 2016 10:14 am
Location: Australia

Re: [BASIC] Object-Oriented Programming

Postby RoryOF » Tue May 03, 2016 4:45 pm

The documentation is linked off
https://wiki.openoffice.org/wiki/Documentation/BASIC_Guide

There are PDF files for 3.2 or 3.3 with all the contents - these are good if you like a manual in your hand. They omit one or two later additions, which I doubt will be of concern. I cannot find URLs for these at present - linesmen working on phone lines so internet connection is uncertain.
Apache OpenOffice 4.1.4 on Xubuntu 16.04.03 (mostly 64 bit version) and infrequently on Win2K/XP
14 October 2016 was Pooh's 90th birthday
User avatar
RoryOF
Moderator
 
Posts: 25518
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: [BASIC] Object-Oriented Programming

Postby Villeroy » Tue May 03, 2016 5:23 pm

User-defined structs are one thing. Object oriented programming is by far more than that. VB has a few OOP capabilities. StarBasic is strictly procedural because there is no sub-classing, no inheritance, no methods.

In VBA you can write design objects in class modules and do something like this:

Code: Select all   Expand viewCollapse view
Set myObj = New MyClass(init_arg_A)
Set myObj2 = New MyClass(init_arg_B)

myObj1.Foo = x
myObj2.Foo = m

myObj1.Bar = y
myObj2.Bar = n

myObj1.callMyMethod("blah", 1, 13)
myObj2.callMyMethod("blurb", 43, 12)

We have 2 different objects myObj1 and myObj2 with the same properties but different property values, with the same user-defined methods callable with different arguments, created from the exact same class module code.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 16.04, OpenOffice 4.x & LibreOffice 5.x
User avatar
Villeroy
Volunteer
 
Posts: 24664
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: [BASIC] Object-Oriented Programming

Postby JPL » Wed May 04, 2016 1:00 pm

Villeroy wrote:
StarBasic is strictly procedural because there is no sub-classing, no inheritance, no methods.

You can find how to bypass some of the constraints or limitations of StarBasic in this matter by reading THIS.

JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm

Re: [BASIC] Object-Oriented Programming

Postby simH » Sat Jun 24, 2017 7:17 am

I am using LibreOffice Calc Version 5.1.6.2 on Ubuntu 16.04LTS and your OOP example works as you indicate. I only have one question if I may. Forgive if it seems silly as I am relying on my OOP experience from some time ago.

Wouldn't allowing access to the Point class private variable _X, from outside the Point Module, violate the principle of information hiding? I can see that the Point class properties "Let" and "Get" are defined public and provide access to the private variables. Then it all seems odd when I can access the private variable _X directly, from another module. Is there any way of restricting access to that Private variable?
Last edited by simH on Sun Jun 25, 2017 11:54 pm, edited 4 times in total.
LibreOffice 5.1.6.2 on Ubuntu 16.04LTS
simH
 
Posts: 7
Joined: Sat Jun 24, 2017 6:38 am
Location: Australia

Re: [BASIC] Object-Oriented Programming

Postby JeJe » Sat Jun 24, 2017 11:16 am

simH

Yes: don't have Let and Get subs to set its value.

What you're picking fault with is how its designed - the point is you can use the variable name _X in another module and you won't inadvertantly change the value in the class module because its private. You need to use Let and Get to set it.

Its not that great an idea to ask questions on the bottom of a 5 year old thread.
Openoffice 4.1.2
Windows 8
JeJe
 
Posts: 122
Joined: Wed Mar 09, 2016 2:40 pm

Re: [BASIC] Object-Oriented Programming

Postby JPL » Sun Jun 25, 2017 6:18 pm

@simH

Indeed setting the Private attribute to a class internal variable should forbid to access its value both for reading or for writing.

However the Private and Public attributes are simply ignored in StarBasic, independently from what they're applied to: class variables, module variables, Subs, Functions, they're all public even when the Private keyword is present. This is IMHO not really linked with the OO programming facilities in StarBasic.

JPL
Windows 7 / LibO 5.3 / OOo 4.1
Ubuntu 16.10 / LibO 5.4
The Access2Base extension for LibO/AOO Base can be downloaded from the LibO/AOO extension centers. It is embedded in LibreOffice >= 4.2.
Its documentation is on http://www.access2base.com.
JPL
Volunteer
 
Posts: 81
Joined: Fri Mar 30, 2012 3:14 pm


Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 4 guests