When I ask “What kind of variable are you?” I don’t mean “Are you an Integer, a String, a Variant, an Object?”. I am asking “are you a value type or a reference type?”. What’s the difference between the two?
Value types hold the value directly. In Xojo this includes Integers of all kinds, Doubles or Colors. When you put a value into one, the memory address for this variable is set to whatever the correct binary representation for the value is. So lines like:
dim i as integer i = 32
- set aside a memory location, in the dim line, to hold an integer
- the second line will put the correct binary representation of “32” into the memory address set aside in step 1
And then there are reference types. Note: This is not the same as “ByRef” in a method parameter declaration although it’s related. Reference types do not store the data in the memory address assigned to the variable. They have a pointer to some other memory area that actually holds the data. So lines like:
dim p as Picture p = new Picture(10,10)
- set aside a memory location, in the dim line, to hold a pointer (reference)
- the second line will allocate enough memory to hold the picture somewhere else in memory and then put the correct address of this block of memory into the memory address set aside in step 1
Most reference types in Xojo are reasonably easy to identify – you have to use New to create one from scratch. But there are a few that might catch you unaware. And the difference between value types and reference types causes no end of confusion with code like this:
dim p1, p2 as Picture p1 = new Picture(10,10) p2 = p1
While many expect that this will “copy” the picture from p1 and create a new one for P2 thats not what happens at all. Instead this code will:
- In the DIM line, set aside memory locations to hold pointers (references), one for each of p1 and p2.
- The second line will allocate enough memory to hold the picture and then put the correct address of this block of memory into the memory address set aside in step 1 for P1.
- The last line will take the address that is in the location for P1 and put it into the location set aside for P2.
This results in both p1 and p2 now containing the same address – they both refer to the same underlying Picture object. So changing either one will make it appear like the other has changed as well.
As I said earlier, most times you have to use New to access a variable that is a reference type. However, arrays are reference types so you have to be careful with them. Suppose you have a module that returns an array and the array is supposed to be set up once and then reused in many places. But the users might alter the array that was returned. Something like the following:
Module Fonts Function FontList() as String() if not mInitialized then for i as integer = 0 to FontCount - 1 mFonts.append Font(i) next mInitialized = true end if return mFonts End Function Private Property mFonts() as string Private Property mInitialized as boolean End Module
and then somewhere else in your application you have
Sub FontUser() dim fontslist() as string = Fonts.FontList() // and lets get rid of all fonts with names starting with "a" for i as integer = fontlist.ubound downto 0 if fontslist(i).left(1) = "a" then fontslist.remove i end if next End Sub
What happens? The code calling the FontList method gets back a reference to the exact same array stored in the module, and then proceeds to remove entries from it. So the next time you call the method they are not present. They appear to have magically disappeared – but they haven’t. Both the FontUsers reference to the array and the one stored in the module refer to the same array and so altering one alters the other.