A class is kind of template. You create that at design time. If you want instaces of that, you create those at runtime (i.e. when your program executes). Your code creates an instance of the class, an object, with the New keyword, thus:
Var myInst1, myinst2 as myClass // These are born with value Nil
myinst1 = new myClass // an instance is born
myinst2 = myinst1 // NOT a new instance; myinst2 points at the same instance as myinst1
Public Function Clone() As MyClass
Dim properties() As Introspection.PropertyInfo
Dim t, tclone As Introspection.TypeInfo
// This works only for primitives and dictionaries of primitives. No arrays, no deep dictionaries.
dim newMyClass As new MyClass
dim cloneproperties() As Introspection.PropertyInfo
cloneproperties = Introspection.GetType(newMyClass).GetProperties
properties = Introspection.GetType(me).GetProperties
For Each p As Introspection.PropertyInfo In properties
t = p.PropertyType
for each pclone as Introspection.PropertyInfo in cloneproperties
tclone = pclone.PropertyType
If pclone.Name = p.Name Then
if tclone.FullName = t.FullName Then
If t.name = "Dictionary" Then
if p.Value(me) <> Nil then
pclone.Value(newMyClass) = Dictionary(p.Value(me)).Clone // Shallow clone
End
Else
pclone.Value(newMyClass) = p.Value(me)
End
End
End
Next
Next
Return newMyClass
End Function
I have a class which I call a variable (is that possible?) which has 40 properties. The variable holds a Question and Answer to it plus a whole lot of properties concerning how it is printed, whether it has a tag-along “Note”, etc. Here’s a pic of part of the window where I edit my puzzles. (I have been publishing one a week for 24 years in the local newspaper.)
Very happy to know this. My puzzle-editing page has a LOT of controls on it and every time I make a small change the whole page has to reprint so anything I can do to speed things up is helpful.
Further expanding on Tim’s explanation, New simply calls the class’s Constructor. This method is often left empty, in which case it just returns an instance, period. But you can add code to the constructor method, or override the constructor of a built-in class with your own constructor method, and do anything you want in it, often initialization or instantiation of objects that are part of the class and properties of each instance. It’s somewhat analogous to the Open event of a window.
For example, if you were to subclass Canvas to make some kind of control that blinks, you’d probably have a Timer as a class property to do the blinking. In the constructor you’d instantiate the timer (with New) and set its mode, period, etc.
Without attempting to solve your issue here is an explanation of byval and byref.
To understand the difference between byval and byref, and the implications of them, you need to consider what is actually happening in the hardware.
(For the purpose of avoiding a bunch of zeros in the examples I am assuming a 16 bit address space.)
When we declare a variable, for instance. Var aValue as UInt16 = 42
The compiler assigns the label ‘aValue’ to an available memory address, say $1000, and writes the byte values 00 42 into $1000 and $1001 respectively. The UInt16 declaration informs the compiler the value takes up 2 bytes and it can not assign $1000 and $1001 to any other label.
When we look at the label aValue in memory we can see it has two different contexts. aValue may be the bytes 00 42 or it may be the memory address $1000.
Let’s declare a subroutine that can take aValue as a parameter foo(aParam As UInt16)
aParam is a variable so the compiler assigns a label to a memory address as it did before.
What get’s written into the contents at aParam at run time when we call, foo(aValue) depends on the declaration of the subroutine.
As we did not specify byval or byref when we declared foo, the compiler presumes byval. When the code executes the contents at aValue is copied into the ‘stack frame’ which foo uses to populate it’s aParam variable.
The contents at aValue remains unchanged. The contents at aParam has been incremented.
If we want to pass the alternative context of aValue, the location in memory the aValue label refers to, we instruct the compiler to pass byref in the subroutine declaration. Now at runtime the memory location of aValue is copied to the stack frame, rather than the contents at the location.
The contents at aParam is unchanged. The contents at aValue has been incremented.
The byref keyword instructs the compiler to pass the address of a value - A reference to a value at a different memory location. At runtime the code modifies the contents at the address that was passed, and that is known as dereferencing.
Why you might want to explicitly pass byref is a whole different article. Suffice to say inappropriate use of byref can be dangerous and with highly abstracted OOP tools like Xojo there is rarely a need.
What is a class, an object variable, an instance and what does the New keyword do?
A Class is an instruction to the compiler. Similar to a Lego instruction pamphlet, it tells the compiler how to small building blocks (bytes, ints, floats and so on) are assembled to form more complicated object types.
Lets’s define a class.
Class MyObject
Property IDNumber as UInt16
Property XPosition as UInt32
Property YPosition as UInt32
End Class
An object variable is a named reference to an object that is defined by a class.
Let’s declare an object variable. The examples assumes a 32bit address space.
Var object1 As MyObject
Label
type
sz_bytes
start_addresss
contents
object1:
MyObject
4
$10000000
00,00,00,00
The declaration caused the compiler to create a label and allocate the 4 bytes needed to hold a 32bit address. Nothing was assigned to object1 so the contents are set to 0 which is also known as the nil or null pointer [1]. Note a MyObject needs at least 10 bytes to hold the property values but the compiler has only reserved the 4 bytes needed for an address.
Declaring an object variable creates a reference to an object but it does not create the object.
Let’s create a MyObject and assign some values to properties
Var object1 As MyObject
Var aCount As UInt16 = 42
object1 = New MyObject
object1.IDNumer = aCount
object1.XPosition = 123450
object1.YPosition = 567890
Code Section
Label
type
sz_bytes
start_addresss
contents
object1:
MyObject
4
$10000000
A0,00,00,00
aCount:
UInt16
2
$10000002
00,2A
Heap Allocation
Label
type
sz_bytes
start_address
contents
MyObject_1.
IDNumber:
UInt16
2
$A0000000
00,2A
MyObject_1.
XPosition:
UInt32
4
$A0000002
00, 01, E2, 3A
MyObject_1.
YPosition:
UInt32
4
$A0000006
00, 08, AA, 52
The New keyword caused the runtime to dynamicallly allocate the memory a MyObject needs to store it’s properties and returned the address of the reservation, which was assigned to the object1 variable by the = operator.
The memory reservation is an instance of a MyObject. An instance is created when physical memory is allocated. An instance is destroyed when physical memory is deallocated.
Note the contents of object1. Passing object1 by value would pass A0000000. Passing object1 by reference would pass $10000000 but after deferencing the value is A0000000.
Let’s declare another MyObject variable and assign object1 to it.
Var object1 As MyObject
Var aCount As UInt16 = 42
Var object2 As MyObject
object1 = New MyObject
object2 = object1
Label
type
sz_bytes
start_addresss
contents
object1:
MyObject
4
$10000000
A0,00,00,00
aCount:
Byte
2
$10000002
00,2A
object2:
MyObject
4
$10000004
A0,00,00,00
When object1 is assigned to object2 the contents at object1 is copied to object2. object1 and object2 are both pointing to a single physical instance of a MyObject at $A0000000 that was created with the New keyword. Any operation carried out on either object1 or object2 will modify the same physical instance at $A0000000.
A Class describes an object.
An object variable is a pointer variable that knows what a class looks like.
An instance is the physical memory an object occupies.
The New keyword creates an instance of an object.
Object variables and instances are independent entities.
[1] Nil objects. Any attempt to read from or write to address 0 triggers a CPU exception.