BBC BASIC for Windows
Programming >> BBC BASIC language >> Object oriented BB4W
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1253444154

Object oriented BB4W
Post by JonR on Sep 20th, 2009, 10:55am

The method I usually use is to have a structure that contains the data of the object and a set of functions and procedures I call to manipulate the object. To demonstrate here's a simple object that contains a real value with routines to create, destroy, compare and check of equivalence:

Code:
      PROC_createObject(obj1{})
      PROC_createObject(obj2{})
      
      obj1.Value=10
      obj2.Value=2
      
      CASE FN_compareObject(obj1{},obj2{}) OF
        WHEN -1:PRINT "obj1 is less than obj2"
        WHEN 0:PRINT "obj1 is equal to obj2"
        WHEN 1:PRINT "obj1 is greater than obj2"
      ENDCASE
      
      PROC_destroyObject(obj1{})
      PROC_destroyObject(obj2{})
      
      END
      
      REM Create a new instance of the object
      DEF PROC_createObject(RETURN obj{})
      DIM obj{Value}
      ENDPROC
      
      REM Compare objects: 0 (=), -1 (<), 1 (>)
      DEF FN_compareObject(obj1{}, obj2{})
      IF obj1.Value = obj2.Value THEN =0
      IF obj1.Value > obj2.Value THEN = 1
      =-1
      
      REM Are both instances of the same object (not tested)
      DEF FN_equalsObject(obj1{}, obj2{})
      =obj1{}=obj2{}
      
      REM Destroy the object
      DEF PROC_destroyObject(RETURN obj{})
      obj.Value=0
 


An alternative method more in keeping with other object oriented languages I develop in is to include all the function pointers in the object structure. This allows everything related to the object itself to be stored in or pointed to by he object, at first glance it appears slightly more complex, which it is internally, but I think it better encapsulates this method of programming and is more intuitive to program with.

Code:
      PROC_createObject(obj1{})
      PROC_createObject(obj2{})
      
      obj1.Value=9
      obj2.Value=10
      
      CASE FN(obj1.Compare)(obj1{},obj2{}) OF
        WHEN -1:PRINT "obj1 is less than obj2"
        WHEN 0:PRINT "obj1 is equal to obj2"
        WHEN 1:PRINT "obj1 is greater than obj2"
      ENDCASE
      
      PROC(obj1.Destroy)(obj1{})
      PROC(obj2.Destroy)(obj2{})
      
      END
      
      REM Create a new instance of the object
      DEF PROC_createObject(RETURN obj{})
      DIM obj{Create,Equals,Compare,Destroy,Value}
      obj.Create = ^PROC_createObject()
      obj.Compare = ^FN_compareObject()
      obj.Equals = ^FN_equalsObject()
      obj.Destroy = ^PROC_destroyObject()
      ENDPROC
      
      REM Compare objects: 0 (=), -1 (<), 1 (>)
      DEF FN_compareObject(obj1{}, obj2{})
      IF obj1.Value = obj2.Value THEN =0
      IF obj1.Value > obj2.Value THEN = 1
      =-1
      
      REM Are both instances of the same object (not tested)
      DEF FN_equalsObject(obj1{}, obj2{})
      =obj1{}=obj2{}
      
      REM Destroy the object
      DEF PROC_destroyObject(RETURN obj{})
      obj.Value=0
      ENDPROC
 


The Create, Equals, Compare and Destroy methods would be common to all objects. The only 'internal' function name the user has to know is the object creator, although once they have at least one object there's nothing stopping them calling object.Create to create more.

Embedding all the methods in the object itself gives the user a consistent interface to objects and allows different methods to be pointed to if the type/instance of the object requires it.

The disadvantages are that including the object methods in the object requires more memory and that object initialisation is more complex (though this could be mitigated by keeping a private copy of a blank initialised object) and that calling functons by address appears to be very slightly slower.

Of course, with both solutions that user always has to pass the object structure to the methods because there is no way the called method can know which object was referenced to call it.

The above code uses DIM to allocate the structure in the BASIC heap for simplicity, a fuller implementation might use HeapAlloc or GlobalAlloc to get memory to store the object. In this case the memory would be freed when the object is destroyed.

Re: Object oriented BB4W
Post by admin on Sep 22nd, 2009, 2:00pm

Quote:
The method I usually use is to have a structure that contains the data of the object and a set of functions and procedures I call to manipulate the object.

For another example see the XMLLIB library, which works the same way.

Quote:
An alternative method more in keeping with other object oriented languages I develop in is to include all the function pointers in the object structure.

I'm not sure you gain a great deal, because in BBC BASIC procedures/functions are always global. Calling them via object pointers adds an undesirable layer of complexity without providing the benefits of a 'true' OO approach of making the PROCs/FNs invisible otherwise.

I'd be inclined simply to use name decoration to achieve a similar effect:

Code:
PROC_MyObject_Create
PROC_MyObject_Compare
PROC_MyObject_Equals 

You'd almost certainly need to decorate the names even using your approach, otherwise how do you distinguish the PROC_createObject() for one object type from the PROC_createObject() of a different object type?

Richard.