GLBasic forum

Main forum => FAQ => Topic started by: MrTAToad on 2010-Jul-25

Title: Using Extended Types
Post by: MrTAToad on 2010-Jul-25
With the imminent release of V8, I thought it might be an idea to have a discussion on extended types. 

As you all know types can be used to group variables into an abstract object to make it easier to manipulate information for a specific purpose - instead of having the variables defined all around the place...

It is therefore a logical step to be able to group functions into a type - this allows functions to be created to the specific type and to allow easy manipulation of its variables.  It keeps things tidy, aid easier code re-use and help debugging too.  Extended types are just TYPE's with functions in them.

Extended types could be described as being like a C++ class, but with some differences :


Self
This command is needed to access the variables within a type - without this you could get some strange and complicated compiler errors.

Name Defining
As GLBasic will not allow types to use duplicate function names, I find it best to distinguish between standard types and extended types by proceeding the function name with a small 't' for standard type or a capital 'T' for a type with functions.  The type name is then used following by the function name, with the two seperated by an underscore '_'

Function and Variable Access
As functions and variables can be directly accessed, it would be best not to do so, and instead have helper functions.  There are many advantages of doing this : easier to debug, put all validation code into one place and the knowledge that you wont be causing extra problems.

Constructor and Destructor
As there isn't the ability to call a function when the type is created or destroyed, the former can be done by calling a function (I usually append Initialise to the prefix) just after the function is defined.

The Types
A standard type could be :

Code (glbasic) Select

TYPE tSomething
    a%
    b
    c$
ENDTYPE


whilst an extended type can be defined as :

Code (glbasic) Select
TYPE TDot
value
FUNCTION TDot_Initialise%:
self.value=123.45
ENDFUNCTION
ENDTYPE

TYPE TSomething
a%
b
c$
dot AS TDot

FUNCTION TSomething_Initialise AS TDot:
dot.TDot_Initialise()
RETURN self.dot
ENDFUNCTION
ENDTYPE

LOCAL some AS TSomething
LOCAL _dot AS TDot

_dot=some.TSomething_Initialise()
DEBUG _dot.value


This example returns the TDot extended type as created in the TSomething class

When defining parameters for functions, be aware the the variables aren't in the local space (yet :) ), so something like :

Code (glbasic) Select
TYPE TDot
value
FUNCTION TDot_Initialise%:x%,y%
self.value=x%*y%*1.2
ENDFUNCTION
ENDTYPE

TYPE TSomething
a%
b
c$
dot AS TDot

FUNCTION TSomething_Initialise AS TDot:x%,y%
dot.TDot_Initialise()
RETURN self.dot
ENDFUNCTION
ENDTYPE

GLOBAL x%,y%
LOCAL some AS TSomething
LOCAL _dot AS TDot

_dot=some.TSomething_Initialise(1,2)
DEBUG _dot.value


will produce the following warnings :

Quote
"Test.gbas"(20) warning : variable already exists : x
"Test.gbas"(20) warning : variable already exists : y

This shows that you can modify a passed type :

Code (glbasic) Select
TYPE TDot
value
FUNCTION TDot_Initialise%:x%,y%
self.value=x%*y%*1.2
ENDFUNCTION

FUNCTION TDot_Display%:
DEBUG self.value+"\n"
ENDFUNCTION
ENDTYPE

TYPE TSomething
a%
b
c$
dot AS TDot

FUNCTION TSomething_Initialise:d AS TDot
self.dot=d

self.dot.TDot_Initialise%(1,2)
self.dot.TDot_Display()

d.TDot_Initialise(6,7)
ENDFUNCTION
ENDTYPE

GLOBAL x%,y%
LOCAL some AS TSomething
LOCAL _dot AS TDot

_dot.TDot_Initialise(2,3)
_dot.TDot_Display()

some.TSomething_Initialise(_dot)
_dot.TDot_Display()


And, of course, they can be in arrays.  This is handy for, say, multiplay games, as you wont need to pass things like player indexes to functions :

Code (glbasic) Select
TYPE TDot
value
FUNCTION TDot_Initialise%:x%,y%
self.value=x%*y%*1.2
ENDFUNCTION

FUNCTION TDot_Display%:
DEBUG self.value+"\n"
ENDFUNCTION
ENDTYPE

TYPE TSomething
a%
b
c$
dot AS TDot

FUNCTION TSomething_Initialise:d AS TDot
self.dot=d

self.dot.TDot_Initialise%(1,2)
self.dot.TDot_Display()

d.TDot_Initialise(6,7)
d.TDot_Display()
ENDFUNCTION
ENDTYPE

GLOBAL x%,y%
LOCAL some[] AS TSomething
LOCAL _dot AS TDot

DIM some[65]
some[0].TSomething_Initialise(_dot)


ADDRESSOF
ADDRESSOF can't be used with a function in an extended type.   This shouldn't matter as all the function would be doing is comparing the contents of two normal types.

Multiple Files
With V8.050 upwards, types can be created in one file and used in another.
Title: Re: Using Extended Types
Post by: Hatonastick on 2010-Jul-26
Thanks for posting this explanation as it clears up one or two questions I had.
Title: Re: Using Extended Types
Post by: Slydog on 2010-Jul-26
QuoteWith V8.050 upwards, types can be created in one file and used in another.

But can a type defined in one file access another type defined in another file?
Title: Re: Using Extended Types
Post by: Hatonastick on 2010-Jul-26
Quote from: Slydog on 2010-Jul-26
QuoteWith V8.050 upwards, types can be created in one file and used in another.

But can a type defined in one file access another type defined in another file?
Only way to find out is to try it. :)
Title: Re: Using Extended Types
Post by: Ian Price on 2010-Jul-26
These appear to be like "Methods" in BlitzMax - these were invaluable OOP routines for me, back when I used BMax.

Nice examples MrTaToad :)
Title: Re: Using Extended Types
Post by: MrTAToad on 2010-Jul-26
QuoteBut can a type defined in one file access another type defined in another file?
No, you can't.

With this in source "test2" :

Code (glbasic) Select
GLOBAL moo%

TYPE B
b
g AS Tg

FUNCTION foo: a%
DEBUG "Here\n"
self.g.Tg_moo()
ENDFUNCTION
ENDTYPE


and this in source "test3" :

Code (glbasic) Select
TYPE Tg
FUNCTION Tg_moo%:
ENDFUNCTION
ENDTYPE


You get "error : call to undefined function : B__g.Tg_moo".  Forward access to extended types is only granted from the main program file and main program.  To get around this you would need to define a local variable (with the extended type) and pass it to the required one.
Title: Re: Using Extended Types
Post by: MrTAToad on 2010-Jul-27
In 8.054, TYPES in source files can now access TYPEs defined in other files.

In 8.064, function names dont have to be different from functions in other types