Using 'Interface' for object-oriented programming in SB

Share your advanced knowledge/code with the community.
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

Using 'Interface' for object-oriented programming in SB

Post by Danilo »

Small example for using Interface with SpiderBasic:

Code: Select all

; The Interface describes the functions/methods of the object
Interface IObject
    Move(x,y)
    MoveF(x.f,y.f)
    Destroy()
EndInterface

; The FuncPointer structure contains the addresses to the functions
Structure IObject_FuncPointer
    Move.i
    MoveF.i
    Destroy.i
EndStructure

; The Structure contains the *vt pointer to the Interface functions, and additional object variable declarations
Structure SObject
    *vt.IObject_FuncPointer
    ; variables:
    objectName.s
EndStructure

; The object functions
Procedure __Move(*o.SObject,x,y)
    Debug "IObject.Move() -> Moving to: "+Str(x)+","+Str(y)
EndProcedure

Procedure __MoveF(*o.SObject,x.f,y.f)
    Debug "IObject.MoveF() -> Moving to: "+StrF(x)+","+StrF(y)
EndProcedure

Procedure __Destroy(*o.SObject)
    Debug "IObject.Destroy()"
    ;Debug "Destroying Object: "+*o\objectName
    FreeMemory(*o\vt)
    FreeMemory(*o)
EndProcedure

; This function creates the object instance
Procedure.i New_Object()
    Protected *o.SObject = AllocateStructure( SObject ) ;! p_o              = spider_AllocateStructure(s_sobject, null);
    If *o
        *o\vt = AllocateMemory( SizeOf(IObject) )       ;! p_o._vt          = spider_AllocateMemory(24);
        If *o\vt = 0
            FreeStructure(*o)
            ProcedureReturn 0
        EndIf
        *o\vt\Move    = @__Move()                       ;! p_o._vt._Move    = f___move;
        *o\vt\MoveF   = @__MoveF()                      ;! p_o._vt._MoveF   = f___movef;
        *o\vt\Destroy = @__Destroy()                    ;! p_o._vt._Destroy = f___destroy;
        *o\objectName = "IObject("+Hex(Random($7FFFFFFF))+")"
        ;Debug "Created Object: "+*o\objectName
    EndIf
    ProcedureReturn *o
EndProcedure

Object1.IObject = New_Object()
Object2.IObject = New_Object()
  
Object1\Move(10, 20)
Object1\Destroy()

Object2\MoveF(10.5, 20.1)
Object2\Destroy()
Last edited by Danilo on Mon Nov 25, 2019 2:17 pm, edited 2 times in total.
cya,
...Danilo
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

Re: Using 'Interface' for object-oriented programming in SB

Post by Danilo »

Example for creating the object directly using JavaScript:

Code: Select all

; The Interface describes the functions/methods of the object
Interface IObject
    Move(x,y)
    MoveF(x.f,y.f)
    Destroy()
EndInterface

; The Structure contains the *vt pointer to the Interface functions
Structure SObject
    *vt
EndStructure

; The object functions
Procedure __Move(*o.SObject,x,y)
    Debug "IObject.Move() -> Moving to: "+Str(x)+","+Str(y)
EndProcedure

Procedure __MoveF(*o.SObject,x.f,y.f)
    Debug "IObject.MoveF() -> Moving to: "+StrF(x)+","+StrF(y)
EndProcedure

Procedure __Destroy(*o.SObject)
    Debug "IObject.Destroy()"
    !delete p_o;
EndProcedure

; This function creates the object instance
Procedure.i New_Object()
    ! var obj = {};
    ! obj._vt = {};
    ! obj._vt._Move    = f___move;
    ! obj._vt._MoveF   = f___movef;
    ! obj._vt._Destroy = f___destroy;
    ! return obj;
EndProcedure

Object1.IObject = New_Object()
Object2.IObject = New_Object()
  
Object1\Move(10, 20)
Object1\Destroy()

Object2\MoveF(10.5, 20.1)
Object2\Destroy()
cya,
...Danilo
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

Re: Using 'Interface' for object-oriented programming in SB

Post by Danilo »

For completeness, using JavaScript inline functions:

Code: Select all

; The Interface describes the functions/methods of the object
Interface IText
    Set(text.s)
    Get.s()
    Destroy()
EndInterface

; This function creates the object instance
Procedure.i New_IText(text.s="")
    ! var obj = {};
    ! obj.theText = v_text;
    ! obj._vt = {};
    ! obj._vt._Set     = function(self, text) { self.theText = text;      };
    ! obj._vt._Get     = function(self)       { return self.theText;      };
    ! obj._vt._Destroy = function(self)       { delete self; return null; };
    ! return obj;
EndProcedure

txt1.IText = New_IText()
txt2.IText = New_IText("My Text")

Debug "txt1: " + txt1\Get()
Debug "txt2: " + txt2\Get()

Debug "-----"

txt1\Set("This is txt1")
txt2\Set("This is txt2")

Debug "txt1: " + txt1\Get()
Debug "txt2: " + txt2\Get()

txt1 = txt1\Destroy()
txt2 = txt2\Destroy()
cya,
...Danilo
the.weavster
Posts: 220
Joined: Sat Mar 01, 2014 3:02 pm

Re: Using 'Interface' for object-oriented programming in SB

Post by the.weavster »

Hi Danilo,

Is there a way to pass an instance of IText to a procedure as a parameter. This doesn't work but demonstrates what I'd like to be able to do:

Code: Select all

Procedure speak(v.IText)
  Debug v\Get()
EndProcedure
the.weavster
Posts: 220
Joined: Sat Mar 01, 2014 3:02 pm

Re: Using 'Interface' for object-oriented programming in SB

Post by the.weavster »

Forget what I wrote there, it does work.

I'm not sure what I did wrong before :? :oops:


Thanks for these tips, they're very helpful :D
Post Reply