The World of User Defined Types

By: Kevin Picone



I N D E X:






About


      The following was written to take the user through the basic usage and concepts associated with Types. The article mostly follows in a top down nature. With the most advanced concepts located towards the bottom. There's key headings all the way through however, so if your already familiar with types you should be able to skim through the headings to brush up on PlayBASIC's implementation.

      Have you read the Variables & ArrayBasics tutorials ? No - might be better starting there then.

Top





Type's, What are they?


      User Defined Types allow users to create our own data types, and are the natural extension of the simpler data types your no doubt already familiar with, like Integers, Floats and Strings. The main difference, is that Types allow us to bind a series of simple data types into a collection. Ideally so we can group together sets of properties that are in some way related to each other. Which is a good programming practice to get into.

Top





Declaration of a User Defined Type


      Lets imagine we wish to store a collection of information about a person. The collected information might cover the persons first, middle, surname (family) name, home address, phone number, type of employment etc etc. While we could store all those pieces of information separately in traditional variables or arrays, a better approach would be to create a User Defined Type (UDT) to house all of individual properties together. So we can manage the group of information tidbits together.


I.e.,

      In this example we're declaring a type called "Person". This type will hold all of the relevant information about a single person in one place.

  
; Declare the "Person" user defined type.
  Type Person
     
   ; These Fields will hold this persons full name
     FirstName$
     MiddleName$
     SurName$
     
   ; This Field will hold this persons Address
     HomeAddress$
     
   ; This Field will hold this persons work Address
     WorkAddress$
     
   ; Phone Number
     PhoneNumber$
     
  EndType
  


      The code above purely shows the declaration of our "Person" type. We can see the type has seven string fields FirstName$,MiddleName$,SurName$,HomeAddress$,WorkAddress$ and PhoneNumber$ are contained within this type. At this point we can't really do much with it, we need to create a variable or array of this type, in order store and retrieve information about our actual person.

Top





Declaring a Typed Variable


      Once a UDT (user defined type) has been declared to PlayBasic, we can then create our own variables and even arrays of that type. To create a typed variable we use the "Dim" command, followed by our Variable Name then the "as type" to specify what data type this variable should use. This will create our variable ready for us to store information in it.


  
; Dimension the variable 'Bill' as type Person. (from above)
  Dim Bill As Person
  


Top





Declaring a Typed Array


      Once a user defined type has been declared to PlayBasic we can then create array's to store collections of individual instances in. Just like regular integer/float & string arrays. To create a typed array, we use the Dim command, followed by our array name, the size and finally "as type" to specify what data type this array should use. This will create our array ready for us to store information in it.

  
; Dimension the array 'People' as type Person. (from above)
  Dim People(1000As Person
  


Top






Initializing Individual Type Variable & Array Elements (the NEW operator)


      When we deal with UDT (User Defined types) be that in Variable or Array form. The dimensioning process declares the Variable or Array to PB as a particular data type. Now during this process, PB builds a container that will hold our Type(s) data in. But it doesn't actually allocate the type memory (a place to store our type fields in) themselves.

      So we can do that two ways.


1) You can use PlayBasic auto allocation feature. This occur any time when you write to a type. It will automatically allocate the a piece of memory for you and place it in the Variable/Array container. So the allocation process occurs totally transparently.

2) Use the NEW operator to explicitly allocate some type memory and assign to our variable/array container.


      While both are acceptable, the latter option just gives you explicit control over what type your allocating.


     Example of explicit type allocation

  
  
; create an array with space for 100 people
  Dim People(100As Person
  
; Explicitly create a NEW person at index 10 in the person() array.
  People(10= New Person
  


Top






Storing Information In Type Variables


      Once we've declared a User defined type and created a variable to hold and retrieve data, we can now happily start filling this variable with information. This is probably the biggest difference you'll notice to using regular variables. That is when we store information in a type variable/array we need to not only specify the variable name, but the field name also. As remember this variable doesn't just contain one piece information anymore (like a normal integer/float or string variable would) but rather, it now houses all the fields of your "person" type. So we have to clearly specify what field we wish to store our information in.

      Note: To separate the Variable and Field names PlayBasic uses the "." character convention.

  
; Dimension the variable 'Bill' as our type Person.
  Dim Bill As Person
  
; Now BILL contains the person fields, so lets assign bills name
; Now lets assign BILL's name fields
  Bill.FirstName$ ="Billy"
  Bill.MiddleName$ ="Bob"
  Bill.Surname$ ="Citizen"
  


Top





Retrieving Information From a Type Variables


      Retrieving information from a type variable or array is the same storing information in it, we simply enter our type name with field in our expression, and PlayBASIC will retrieve this information for you.

  
; Declare the "Person" user defined type.
  Type Person
   ; These Field hold the person full name
     FirstName$
     MiddleName$
     SurName$
   ; This Fields will hold this persons Address
     HomeAddress$
   ; This Field will hold this persons work Address
     WorkAddress$
   ; Phone Number
     PhoneNumber$
  EndType
  
; Dimension the variable 'Bill' as our type Person.
  Dim Bill As Person
  
; Now BILL contains the person fields, so lets assign bills name
; Now lets assign BILL's name fields
  Bill.FirstName$ ="Billy"
  Bill.MiddleName$ ="Bob"
  Bill.Surname$ ="Dude"
  
; Display Bills Name fields
  Print Bill.firstname$
  Print Bill.MiddleName$
  Print Bill.Surname$
  


Top






What Kind of Fields can User Defined Type Contain ?


      At the time of writing (PlayBASIC Version 1.64k) user defined type fields are limited to the following.


* Byte
* Word
* Integer
* Float
* Strings$
* Static Arrays(Integer, Float, Strings) (1D only)
* Nested User Defined types.


  
  
  Type MyType
     
   ; Implicitly declare fields.
   ; With implicit declares, PB assumes the data type from the field names
   ; post fix (if any)
     
   ; declare integer field
     MyIntegerField
     
   ; declare float field
     MyFloatField#
     
   ; declare string field
     MyStringField$
     
     
   ; explicit declares (notice the post fixes aren't required)
     MyOtherIntegerField As Integer
     MyOtherFloatField As Float
     MyOtherStringField As String
     
   ; declare Statically sized Array Fields (Only 1D arrays are supported)
     MyIntegerArray(10)
     MyFloatArray#(20)
     MyStringArray$(30)
  EndType
  



Note: We're planning on expanding the field support in the future. So when in doubt, try them !

Top









What are STATIC ARRAY FIELDS ?


      Array Fields within types can often be a source of confusion for new programmers, which is no great surprise given the amount of terminology being thrown around. If you've been read through the ArrayBasics tutorial or had a mess about with the DIM command, then you're likely to assume that array fields within a type, are the same as those others. But they're actually not.

      On the surface, static array fields and regular dim'd arrays might seem to be the same concept, until you peel away to see how they're implemented. When we declare an array field within a type, PlayBASIC builds the type structure (during compilation) with a predefined chunk of memory at this position within the type.

      So if we had a type with a couple of integer fields and a static 1D integer array field like the example bellow, the compiler builds this structure up in memory before the program ever runs. Since it's built at compile time, the type structure can't be modified while our program is running. So the Values field will be permanently constructed to hold 5 (0 to 4) separate integers in the TestType structure.

  
  Type  TestType
     Xpos As Integer
     Ypos As Integer
     Values(4)
  EndType
  


      Peeling deeper inside this type declaration and we could actually think of our Values fields, not as an array but rather a collection of individual fields. In the following example, we've created a compatible data structure, even though it doesn't use an array at all.

  
  Type  TestType_UNrolled
     Xpos As Integer
     Ypos As Integer
     Value_0
     Value_1
     Value_2
     Value_3
     Value_4
  EndType
  


      How is this the same ? -- Well, they both define two ways of looking at the the same structure of memory. If we allocated and filled in a type of TestType, we could actually read it using TestType_UNrolled .

      Like so,

  
  Type TestType
     Xpos As Integer
     Ypos As Integer
     Values(4)
  EndType
  
  Type TestType_UNrolled
     Xpos As Integer
     Ypos As Integer
     Value_0
     Value_1
     Value_2
     Value_3
     Value_4
  EndType
  
  Dim Me As TestType Pointer
  
  me = New TestType
  
; set the X & Ypos valies to something
  Me.Xpos = 100
  Me.Ypos = 200
  
; Use a loop to put something in the static array field
  For lp =0 To 4
     Me.Values(lp) = (lp+1)*123
  Next
  
  
  
  Dim Viewer As TestType_UNrolled Pointer
  
  // Clone/Copy the address that ME is current pointing at,
  // into VIEWER pointer
  
  Viewer=Me
  
  
  // Show the XPOS fields
  
  Print Me.Xpos
  Print Viewer.Xpos
  Print ""
  
  // Show the YPOS fields
  Print Me.Ypos
  Print Viewer.Ypos
  Print ""
  
  
  // Show the contents Values index 0
  Print Me.Values(0)
  Print Viewer.Value_0
  Print ""
  
  // Show the contents Values index 1
  Print Me.Values(1)
  Print Viewer.Value_1
  Print ""
  
  // Show the contents Values index 2
  Print Me.Values(2)
  Print Viewer.Value_2
  Print ""
  
  // Show the contents Values index 3
  Print Me.Values(3)
  Print Viewer.Value_3
  Print ""
  
  // Show the contents Values index 4
  Print Me.Values(4)
  Print Viewer.Value_4
  Print ""
  
  Sync
  WaitKey
  


      This works because the two patterns of memory are formatted identically, using the array version is just easier for the programmer, since they can loop through the individual cells. What is demonstrates though is the array firstly embedded in the data and that's there structural header information about the array stored in within the type.

      So far, it looks like a regular array on the surface, but it's here the similarity ends. With a regular array, we can use the array commands to do all kinds of handy things from managing it's size (DIM / REDIM), bounds protection, searching, copying, recreating , pass arrays into / out of functions etc etc We can do this because PlayBASIC avoids referring to the arrays memory directly. Rather it uses a special high level HANDLE interface (unique numeric ID's) when querying, passing or changing the information (the raw memory) inside of it. This helps create a distance between your program code and the raw array data bellow it.

      Static Array Fields in user defined types are as the name suggests, static and don't have high level handle interface of dynamic arrays, which is demonstrated ion the previous example So when we set or get information held in an array field, we're reading/writing directly to that particular location in memory inside of the type structure. The static array is a pre-computed area within a type structure, so we can't change it's size, or apply any of the array command set functionality to it.


      Now since dynamic and static arrays appear similar on the surface, but are radically different internally, it's not uncommon for new PlayBASIC programmers to try and mix and match them with the arrays commands. The Static array doesn't have a high level Handle interface, so that just won't work.

      For example,
  
  Type PlayerCharacters
     Xpos As Float
     Ypos As Float
     Inventory(4)
     Name$
  EndType
  
  Dim Player(2As PlayerCharacters
  
; query the dynamic PLAYER() array by handle for the
; number of elements within the first dimension
  Print GetArrayElements(Player())
  
  
  Sync
  WaitKey
  


      This works because we're passing the GetArrayElements() the handle of the dynamic array Player(), but what if we try and query the number of elements in the Inventory$() field with one of the players ?

  
  Type PlayerCharacters
     Xpos As Float
     Ypos As Float
     Inventory(4)
     Name$
  EndType
  
  Dim Player(2As PlayerCharacters
  
; query the dynamic PLAYER() array by handle for the
; number of elements within the first dimension
  Print GetArrayElements(PLayer())
  
  
; Alloc this type
  Player(1= New PlayerCharacters
  
  
; Try and query the static array field Inventory within
; player 1
  Print GetArrayElements(PLayer(1).Inventory())
  
  
  Sync
  WaitKey
  



      This won't even compile, let alone work. This is because the statement Player(1).Inventory() isn't returning a handle to the Inventory field array, it can't, static arrays don't use them, rather it's returning the physical pointer (Address) of the first field of the inventory within the structure.

      You can demonstrate this yourself with the following,

  
  Type PlayerCharacters
     Xpos As Float
     Ypos As Float
     Inventory(4)
     Name$
  EndType
  
  Dim Player(2As PlayerCharacters
  
  
; Alloc this type
  PLayer(1= New PlayerCharacters
  
  
; declare an Integer Pointer
  Dim Ptr As Integer Pointer
  
  
; get the address of the inventory field within player(1)
  Ptr =PLayer(1).Inventory
  
; write 45 to this address in memory
  *Ptr = 45
  
; show what's at this location
  Print *Ptr
  
; query what's in the inventory at index 0
  Print PLayer(1).Inventory(0)
  
  
  Sync
  WaitKey
  
  



Top








Nesting Types (Declaring Typed fields)



      In our previous examples we've been building a type to house all the fields relating to our person. While perfectly workable at the moment, more information we store in our person, the more rigid things become dealing with them. So as types get bigger (store more and more information) it's often easier to break them down into smaller and more focused types.

      Lets look at this from our of Person type example. Currently our person contain fields, but what if we wanted to store more robust information relating this Persons Home and Work details. For example stuff like Address, Road, State, ZipCode, Country, Phone Number. While we could use something like the following, it's not the most elegant solution.

  
; Declare the "Person" user defined type.
  Type Person
     
   ; These Field hold the person full name
     FirstName$
     MiddleName$
     SurName$
     
   ; The following field group contain info about this persons Home address
     Home_Address$
     Home_Street$
     Home_State$
     Home_ZipCode$
     Home_Country$
     Home_PhoneNumber$
     
   ; The following field group contains info about this persons Work address
     Work_Address$
     Work_Street$
     Work_State$
     Work_ZipCode$
     Work_Country$
     Work_PhoneNumber$
  EndType
  


      As you can see, in this example we have two groups of fields storing information relating the Home and Work addresses of this person. Notice how these groups all share the same basic fields. The only distinguishing difference is the "Work_" or "Home_" prefix , that has been built into each individual field. While this is a usable approach, the main issue with it, is that we can't deal with our sub groups of Work or Home fields separately.

      This presents us the perfect opportunity to create a second smaller type called "HomeInfo". This type will hold all the fields that a house address requires. We'll then use this type to create a two nested type fields HOME and WORK. Both of fields with be of type HomeInfo inside our person.

I.e

  
; Declare the "HouseInfo' User Defined Type
  Type HouseInfo
   ; The following field group contain info about this persons Home address
     Address$
     Street$
     State$
     ZipCode$
     Country$
     PhoneNumber$
  EndType
  
; Declare the "Person" user defined type.
  Type Person
     
   ; These Field hold the person full name
     FirstName$
     MiddleName$
     SurName$
     
   ; Declare HOME as a nested HouseInfo type
     Home As Houseinfo
     
   ; Declare Work as a nested HouseInfo type
     Work As HouseInfo
  EndType
  


      The first thing you'll notice is that by creating the HomeInfo type and nesting it within our Person type as Work & Home, we've actually reduced the declaration code somewhat. That's not the only advantage though, so here's some others are probably less obvious.

      Advantages of separating the 'HomeInfo"


*) If we make changes to HomeInfo (Add/Remove fields), then every other type or function that uses HomeInfo will automatically be compatible with this change. (It wouldn't have been before)

*) HomeInfo can be used on it's own or nested within in other types as well.

*) We can make Assignments between types and nested types. (So we can copy all the fields in HomeInfo by assigning one to the another. i.e Me.Work = Me.Home.)

*) We can NULL (clear) all the fields in type or Nested type. (So we could clear a person's work address details by Me.Work = Null)

*) Type Pointers (nested or other wise) can be passed into or out of Functions & Psubs. This is the biggest benefit and taps into the basic programming ideals found in Object Orientation design. By passing type pointers into functions, we can build function interfaces for explicitly dealing with any particular type. These interfaces might just be code for setting certain properties, changing them, doing a calculation or simply receiving new properties. It's totally up to you. The benefit of this approach is that this interface of functions could be used with every occurrence of the Type their designed for. Using our running example again, this means that we could now roll a general purpose function to set all the fields found in our HomeInfo type. Then we could use this same function to set both the Home & Work fields within our person.




      Note: Make sure you examine the Type Tutorial examples. These can be found in the \Projects\Tutorials\Types.

Top





Making Assignments Between types (Variables & Arrays)


      Type assignments allow us to copy all the fields of a types from one place to another. The syntax follows the same format as a regular variable assignment, just that we have to explicitly name the type fields we wish to copy to/from. So we are copying between two typed variables the syntax should look like this I.e ( DestVariable.ThisType = SourceVariable.ThisType) During the COPY, PB will allocate the destination type automatically if doesn't already exist. So after copying, we'll have a new separate clone of the original.

      It's important to explicitly declare the field you wish to copy, otherwise PB will assume you want to read/write between type elements. (ie. DestVariable=SourceVariable) The problem with this, which is perfectly legal coding practice, is that your moving the types Handle from the source variable into the destination variable, rather than copying it. So now both variables would contain the same handle. So their both pointing to the same data in memory. Therefore, if you change one, the other will change.

      You can copy between any pair of types you like, be they typed variables,
arrays, a combination of variables/arrays, nested within other types, or even in the same type if you like. So it's pretty flexible in that regard. The basic of which are demonstrated in the following example.

  
  
  Type NameInfo
     First$
     Middle$
     Last$
  EndType
  
  
; Declare the "HouseInfo' User Defined Type
  Type HouseInfo
   ; The following field group contain info about this persons Home address
     Street$
     State$
     ZipCode$
     Country$
  EndType
  
  
; Declare the "Person" user defined type.
  Type Person
     
   ; Declare the name field
     Name As NameInfo
     
   ; Declare HOME as a nested HouseInfo type
     Home As Houseinfo
     
   ; Declare Work as a nested HouseInfo type
     Work As HouseInfo
  EndType
  
  
;Declare the typed variable BILL as type Person
  Dim Bill As Person
  
;Declare the typed variable BILL2 as type Person
  Dim Bill2 As Person
  
  
; Init Bills personal info
  SetName(Bill.name,"Billy","Bob","Dude")
  
  SetHouseInfo(Bill.Home,"45 Cool Street","Cool State","1234","Land")
  
; copy Bills home address to his work address also
  Bill.Work = Bill.Home
  
  
; Copy Bill.person complete into BIll2
  Bill2.person = Bill.Person
  
; SHow the state of BIll and Bill2
  ShowPerson Bill()
  ShowPerson Bill2()
  
  
  Sync
  WaitKey
  
  
  
Function SetName(me As NameInfo Pointer,FirstName$,middlename$,lastname$)
  Me.first =FirstName$
  Me.Middle =MiddleName$
  Me.last =LastName$
EndFunction
  
  
Function SetHouseInfo(me As houseInfo Pointer,Street$,State$,zipcode$,country$)
  Me.Street=Street$
  Me.State=State$
  Me.ZipCode=ZipCode$
  Me.Country=Country$
EndFunction
  
  
Function ShowPerson(me.Person)
  Print "<-----Person Details------>"
  Print "name:"+Me.name.first+","+Me.Name.Middle+","+Me.name.last
  ShowHouseInfo(me.work,"*Work Address*")
  ShowHouseInfo(me.home,"*Home Address*")
EndFunction
  
  
Function ShowHouseInfo(me As houseInfo Pointer,Title$)
  Print TItle$
  Print "Street"+me.Street$
  Print "State:"+Me.State
  Print "ZipCode$:"+Me.ZipCode
  Print "Country:"+Me.Country
  Print ""
EndFunction
  
  
  


Top






Type Inheritance (Create New Types from Existing Types )


      Inheritance is another one of those concepts taken from the world of Object Oriented programming. The concept is simple, but it's importance is often overlooked, in particular in regards to maintaining your programs structure and expandability. Conceptually Type inheritance allows us to create new types (children) from existing types (the parent). These new child types inherit all the fields of the parent. From here you can then add extra unique fields to the child type. This allows us to create chains (hierarchies) of descendant types.

      In this example we'll rework our running "Person" example. But this time we'll rename Person as BasePerson type. This new type will be the parent from which all child types are derived. The parent will only contain those fields that are common to all people. Fields like Name, Age, Height ,Weight and hair colour for example. From here, we'll use inheritance to spawn a MALE and FEMALE child types. Adding any unique fields to these new types.

  
  Type tName
     First$
     Middle$
     Last$
  EndType
  
  
; Create the BASE PERSON type
  Type BasePerson
     Name As tName
     Age As Integer
     Height As Integer
     Weight As Integer
     HairColour As String
  EndType
  
  
; Create the MALE type from the BasePerson
  Type Male As BasePerson
     
   ; Add fields to the MALE type that are uniquely Male
     
   ; Flag to hold that this guy
     Has_Mustache
     
   ; This guy has a beard
     Has_Beard
     
  EndType
  
  
; Create the FEMALE type from the BasePerson
  Type FeMale As BasePerson
   ; Add fields to the MALE type that are uniquely Male
     
     Bra_size
  EndType
  
  
; erm, sorry ladies, I'm a guy,  so what do I know about women !.
  


      In this example we're created two different child types from the same parent. It's important to understand that both the MALE and FEMALE types would now contain all of the base Parent fields as well as their uniquely declared fields. So if we were to examine the fields inside MALE & FEMALE types it's the equivalent of the following.

  
; Create the MALE type
  Type Male
     Name As tName
     Age As Integer
     Height As Integer
     Weight As Integer
     HairColour As String
     
   ; Flag to hold that this guy
     Has_Mustache
     
   ; This guy has a beard
     Has_Beard
     
  EndType
  
  
; Create the FEMALE type
  Type FeMale
     Name As tName
     Age As Integer
     Height As Integer
     Weight As Integer
     HairColour As String
     
   ;
     Bra_size
  EndType
  


      While we could happily create our types individually like the second example. Inheritance has few benefits that you should at least familiarize yourself with. But to be honest it often depends upon the size of the project to which approach you'll choose to use.

      Benefits cans be,


* Like Nested Types, Inheritance can help us reduce Type Declaration code

* Inheritance can be used to copy / rename types. So our Child Type declaration (ie Type Child as Parent) doesn't need to have new fields. It could be used to change a type name if you wanted.

* Child Types can be passed into functions that have a suitable Parent type as input parameter.

* Typed Arrays & Variables created a parent type, can hold not only the parent but the children types also. So the array can be used to house a collection of different types within the one container. The TypeOF() can be used to determine the TypeIndex of any particular element within an array or variable.



  
  Type tName
     First$
     Middle$
     Last$
  EndType
  
  
; Create the BASE PERSON type
  Type BasePerson
     Name As tName
     Age As Integer
     Height As Integer
     Weight As Integer
     HairColour As String
  EndType
  
  
; Create the MALE type from the BasePerson
  Type Male As BasePerson
     
   ; Add fields to the MALE type that are uniquely Male
     
   ; Flag to hold that this guy
     Has_Mustache
     
   ; This guy has a beard
     Has_Beard
     
  EndType
  
  
; Create the FEMALE type from the BasePerson
  Type FeMale As BasePerson
   ; Add fields to the FEMALE type that are uniquely FeMale
     
     Bra_size
  EndType
  
  
  
; dimension the PEOPLE array as the PARENT type Base person,
; this array can now hold the PARENT and CHILDREN of
; this parent in the same array.
  Dim People(10As BasePerson
  
; Alloc a MALE at index position 1
  People(1= New Male
  
; Alloc a FeMALE at index position 2
  People(2= New FeMale
  
; run through the array and check what types are stored in it
  For lp=1 To 10
     Select TypeOf(People(lp))
         Case Male
             Print "Person "+Str$(lp)+" is Male"
         Case Female
             Print "Person "+Str$(lp)+" is FeMale"
     EndSelect
  Next
  Sync
  WaitKey
  
  


Top





Passing Types To Functions (Variables + Arrays )


      Types and Functions go hand in hand. While types allow us to group data together, functions allow us to roll pieces of code that can perform a particular calculation or operation upon a data set. Now hopefully you've already familiar with functions & Psubs (if not, be sure to brush over the Tutorial on them). So lets get the nut and bolts about how we can pass Typed Variables/Arrays and pointers into functions.

      This really one of the more advance subjects relating to Types in PlayBasic. Failure to get your head around these different approaches will no doubt see your programs suffer. Don't be afraid though, their bark is nastier than their bite and once you come to grips with them, you'll have given yourself the best opportunity to develop cleaner, faster, and more easily expandable programs!

      In PlayBasic we have three basic controls over dealing with typed data (Arrays/Variables) in general, those being "Handle", "Element" and "Pointer".






      Handles() - When we talk about handles, we are referring to the entire variable/array container, and not the individual items this container may house. To pass by handle we use the closed bracket symbol at the end of our variable/array name. Ie. MyArrayHandle()

ie

  
; This is really a nothing example, it's just showing how to pass
; typed arrays by handle into user functions.
  Type Person
   ; cut down the  fields to reduce the size of this example
     FirstName$,MiddleName$,LastNam$
  EndType
  
  
; Create the people array of type person with
; enough room to hold 10 people
  Dim People(10As Person
  
  
; create (allocate) a person at element #1 & 5
  People(1= New person
  People(5= New person
  
; Call our delete function to run through and NULL
; all of the elements
  Delete_All_People People()
  
  Sync
  WaitKey
  
  
; Create a function that will accept a typed array of type PEOPLE
; as input parameter
Function Delete_All_People(Me().Person)
; The entire People() array has been passed into the this function.
; Therefore inside the function we now use the ME() array to access the passed
; array. You can also passed Typed Variables in, as long as they are the
; type (Person)
  
; Loop though all the elements in the array and NULL them
  For lp=0 To GetArrayElements(Me(),1)
     If Me(lp)
        Me(lp) = null
        Print "Deleted Element:"+Str$(lp)
     EndIf
  Next
EndFunction
  
  
  




     Element - When we address a typed array/variable by element, were reading/writing into the array/variable container and grabbing the handle of an individual type. The Handle of the type is much like a Where not addressing the data fields within a particular type though, but the handle of containing structure that holds all of this types fields.


  
  
; Create Type call my object
  Type MyObject
   ; fields would go here obviously
  EndType
  
  
; Create an Array of points
  Dim Table(10As MyObject
  
; Manually create (allocate) a MyObject at element 5 & 6
  Table(5= New MYObject
  Table(6= New MYObject
  
  
; Print the Handle of this type
  Print "Element Handle:"+Str$(Table(5))
  Print "Element Handle:"+Str$(Table(6))
  
  
; Print the TYPEINDEX of element 50 in our table array
  Print " Type Index:"+Str$(TypeOf(Table(5)))
  Print " Type Index:"+Str$(TypeOf(Table(6)))
  
  
; variable example
  Dim MyVariable As MyObject
  
; Manually alloc the object
  MyVariable = New MyObject
  
  Print "Element Handle:"+Str$(MyVariable)
  Print " Type Index:"+Str$(TypeOf(MyVariable))
  
  
  Print "---> Deleting Them <---"
  
; You can Delete the type at an element by
; writing a NULL to it
  Table(5= null
  Table(6= null
  MyVariable = null
  
  
; Print the Handle of this type
  Print "Element Handle:"+Str$(Table(5))
  Print "Element Handle:"+Str$(Table(6))
  Print "Element Handle:"+Str$(MyVariable)
  
  
  Sync
  WaitKey
  


     You can query the type of any returned element, using the "TypeOF()" function. This Function returns the Type INDEX of the queried element. Both type variable & arrays can house not only types of their parent type declaration, but child types (types inherited from the parent) also. So you could store everything in the one array or variable if you like !

I.e.

  
  Type BaseObject
   ; some fields here
  EndType
; inherit alein1 from base object
  Type Alien1 As BaseObject
  EndType
; inherit Player from the base object type
  Type Player As BaseObject
  EndType
  
; Create
  Dim Objects(100As BaseObject
  Object(1)=New player
  Object(2)=New Alien1
  
  For lp=0 To 100
     Select TypeOf(Object(lp))
         Case Player
             Print "Handle Player"
         Case Alien1
             Print "Handle Alien"
     EndSelect
  Next
  



     Pointer Addressing - Pointers give the address in memory of a particular type instance. So by pointer uses the address of this type instance (the first field in type), and not the structure if came from. You can get a pointer to any element by adding the ."TypeName" after addressing the element. You can also get the pointer to any nested types. This allows us to copy type structures between instances directly. Moreover you can write totally generic functions that accept/return typed pointers.

ie.

  
; declare the pos type
  Type Pos
     x,y
  EndType
  
  
; delcare another type with some nested Pos fields in it
  Type MyObject
     Dot1 As Pos
     Dot2 As Pos
  EndType
  
  
; dim Item as My object type
  Dim Item As MyObject
  
; Allocate a nice new shiny MyObject and place it into Item
  Item= New MyObject
  
; pass the pointer of the nested position type
; from within Base Object to the set point function
  SetPoint(Item.Dot1, 100,200)
  SetPoint(Item.Dot2, 300,200)
  
; Pass them to the draw function
  DrawPoint(Item.Dot1)
  DrawPoint(Item.Dot2)
  
  
  Sync
  WaitKey
  
  
  
  
; Delcare a FunctionSetPoint to accept the pointer
; ME of type POS and the X + Y coorss
Function SetPoint(me As pos Pointer,x,y)
  me.x=x
  me.y=y
EndFunction
  
  
Function DrawPoint(me As pos Pointer)
  Dot me.x,me.y
EndFunction
  
  


Top




 
Related Info: ArrayBasics | Dim | FreeCell | Functions&Psub | GetFreeCell | Loops | New | Null | Pointer | Type | Variables :
 


(c) Copyright 2002 - 2024 - Kevin Picone - PlayBASIC.com