-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathObjects.htm
632 lines (556 loc) · 51.4 KB
/
Objects.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
<!DOCTYPE HTML>
<html lang="es">
<head>
<title>Objects - Definition & Usage | AutoHotkey</title>
<meta name="description" content="Learn details about basic usage of objects, extended usage of objects, custom objects, default base object and implementation of objects." />
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="static/theme.css" rel="stylesheet" type="text/css" />
<script src="static/content.js" type="text/javascript"></script>
<style>
ul.list_of_p p { margin: 0.5em 0; }
ul.list_of_p li { margin: 1em 0; }
</style>
</head>
<body>
<h1>Objetos</h1>
<p>An <i>object</i> in AutoHotkey is an abstract datatype which provides three basic functions:</p>
<ul>
<li>GET a value.</li>
<li>SET a value.</li>
<li>CALL a method (that is, a function which does something with the target object).</li>
</ul>
<p>Related topics:</p>
<ul>
<li><a href="Concepts.htm#objects">Objects</a>: General explanation of objects.</li>
<li><a href="Concepts.htm#object-protocol">Object Protocol</a>: Specifics about how a script interacts with an object.</li>
</ul>
<p><b>IsObject()</b> can be used to determine if a value is an object:</p>
<pre>Result := IsObject(<i>expression</i>)</pre>
<p>See <em>Object Types</em> in the documentation side bar for a list of standard object types. There are three fundamental types:</p>
<ul>
<li><a href="lib/Object.htm"><b>Object</b></a>: the basic type of all user-defined objects, simple arrays and associative arrays.</li>
<li><strong>Built-in objects</strong>, such as <a href="lib/File.htm">File</a>. Built-in objects have a strict set of properties and methods and do not permit new properties or methods to be added.</li>
<li><strong>COM wrapper objects</strong>. These typically represent a COM or "Automation" object implementing the <a href="https://docs.microsoft.com/windows/desktop/api/oaidl/nn-oaidl-idispatch">IDispatch interface</a>, but are also used to <a href="lib/ComObjActive.htm">wrap values of specific types</a> to be passed to COM objects and functions. COM objects are implemented by external libraries, so often differ in behaviour to AutoHotkey objects. </li>
</ul>
<p>Support for objects requires <span class="ver">[AHK_L 31+]</span>, but some features may require a later version.</p>
<h2 id="toc">Tabla de contenidos</h2>
<ul>
<li><a href="#Usage">Basic Usage</a> - <a href="#Usage_Simple_Arrays">Simple Arrays</a>, <a href="#Usage_Associative_Arrays">Associative Arrays</a>, <a href="#Usage_Objects">Objects</a>, <a href="#Usage_Freeing_Objects">Freeing Objects</a>, <a href="#Usage_Remarks">Remarks</a></li>
<li><a href="#Extended_Usage">Extended Usage</a> - <a href="#Function_References">Function References</a>, <a href="#Usage_Arrays_of_Arrays">Arrays of Arrays</a>, <a href="#Usage_Arrays_of_Functions">Arrays of Functions</a></li>
<li><a href="#Custom_Objects">Custom Objects</a> - <a href="#Custom_Prototypes">Prototypes</a>, <a href="#Custom_Classes">Classes</a>, <a href="#Custom_NewDelete">Construction and Destruction</a>, <a href="#Meta_Functions">Meta-Functions</a></li>
<li><a href="#Default_Base_Object">Default Base Object</a> - <a href="#Automatic_Var_Init">Automatic Var Init</a>, <a href="#Pseudo_Properties">Pseudo-Properties</a>, <a href="#Default__Warn">Debugging</a></li>
<li><a href="#Implementation">Implementation</a> - <a href="#Reference_Counting">Reference-Counting</a>, <a href="#Implementation_Pointers">Pointers to Objects</a></li>
</ul>
<span id="Syntax"></span><h2 id="Usage">Basic Usage</h2>
<h3 id="Usage_Simple_Arrays">Simple Arrays <span class="ver">[v1.1.21+]</span></h3>
<p>Create an array:</p>
<pre>Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)</pre>
<p>Retrieve an item:</p>
<pre>Value := Array[Index]</pre>
<p>Assign an item:</p>
<pre>Array[Index] := Value</pre>
<p>Insert one or more items at a given index using the <a href="lib/Object.htm#InsertAt">InsertAt</a> method:</p>
<pre>Array.InsertAt(Index, Value, Value2, ...)</pre>
<p>Append one or more items using the <a href="lib/Object.htm#Push">Push</a> method:</p>
<pre>Array.Push(Value, Value2, ...)</pre>
<p>Remove an item using the <a href="lib/Object.htm#RemoveAt">RemoveAt</a> method:</p>
<pre>RemovedValue := Array.RemoveAt(Index)</pre>
<p>Remove the last item using the <a href="lib/Object.htm#Pop">Pop</a> method:</p>
<pre>RemovedValue := Array.Pop()</pre>
<p>If the array is not empty, <a href="lib/Object.htm#MinMaxIndex">MinIndex</a> and <a href="lib/Object.htm#MinMaxIndex">MaxIndex</a>/<a href="lib/Object.htm#Length">Length</a> return the lowest and highest index currently in use in the array. Since the lowest index is nearly always 1, MaxIndex usually returns the number of items. However, if there are no integer keys, MaxIndex returns an empty string whereas Length returns 0. Looping through an array's contents can be done either by index or with a For-loop. Por ejemplo:</p>
<pre>array := ["one", "two", "three"]
<em>; Iterate from 1 to the end of the array:</em>
<a href="lib/Loop.htm">Loop</a> % array.Length()
MsgBox % array[A_Index]
<em>; Enumerate the array's contents:</em>
<a href="lib/For.htm">For</a> index, value in array
MsgBox % "Item " index " is '" value "'"
</pre>
<span id="Arrays"></span><h3 id="Usage_Associative_Arrays">Associative Arrays <span class="ver">[v1.1.21+]</span></h3>
<p>An associative array is an object which contains a collection of unique keys and a collection of values, where each key is associated with one value. Keys can be strings, integers or objects, while values can be of any type. An associative array can be created as follows:</p>
<pre>Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)</pre>
<p>Using the <code>{key:value}</code> notation, quote marks are optional for keys which consist only of word characters. Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, <code>{(KeyVar): Value}</code> and <code>{GetKey(): Value}</code> are both valid.</p>
<p>Retrieve an item:</p>
<pre>Value := Array[Key]</pre>
<p>Assign an item:</p>
<pre>Array[Key] := Value</pre>
<p>Remove an item using the <a href="lib/Object.htm#Delete">Delete</a> method:</p>
<pre>RemovedValue := Array.Delete(Key)</pre>
<p>Enumerating items:</p>
<pre>array := {ten: 10, twenty: 20, thirty: 30}
<a href="lib/For.htm">For</a> key, value in array
MsgBox %key% = %value%</pre>
<p>Associative arrays can be sparsely populated - that is, <code>{1:"a",1000:"b"}</code> contains only two key-value pairs, not 1000.</p>
<p id="same_thing">In AutoHotkey v1.x, simple arrays and associative arrays are the same thing. However, treating <code>[]</code> as a simple linear array helps to keep its role clear, and improves the chance of your script working with a future version of AutoHotkey, which might differentiate between simple arrays and associative arrays.</p>
<h3 id="Usage_Objects">Objects <span class="ver">[AHK_L 31+]</span></h3>
<p>For all types of objects, the notation <code>Object.LiteralKey</code> can be used to access a property, array element or method, where <em>LiteralKey</em> is an identifier or integer and <em>Object</em> is any expression. Identifiers are unquoted strings which may consist of alphanumeric characters, underscore and, in <span class="ver">[v1.1.09+]</span>, non-ASCII characters. For example, <code>match.Pos</code> is equivalent to <code>match["Pos"]</code> while <code>arr.1</code> is equivalent to <code>arr[1]</code>. There must be no space after the dot.</p>
<p><strong>Examples:</strong></p>
<p>Retrieve a property:</p>
<pre>Value := Object.Property</pre>
<p>Set a property:</p>
<pre>Object.Property := Value</pre>
<p>Call a method:</p>
<pre>ReturnValue := Object.Method(Parameters)</pre>
<p>Call a method with a computed method name:</p>
<pre>ReturnValue := Object[MethodName](Parameters)</pre>
<p>Some properties of COM objects and user-defined objects can accept parameters:</p>
<pre>Value := Object.Property[Parameters]
Object.Property[Parameters] := Value</pre>
<p><strong>Related:</strong> <a href="lib/Object.htm">Object</a>, <a href="lib/File.htm">File Object</a>, <a href="lib/Func.htm">Func Object</a>, <a href="lib/ComObjCreate.htm">COM object</a></p>
<p><b>Known limitation:</b></p>
<ul><li>Currently <code><span class="dull">x</span>.y[z]<span class="dull">()</span></code> is treated as <code><span class="dull">x</span>["y", z]<span class="dull">()</span></code>, which is not supported. As a workaround, <code><span class="red">(</span><span class="dull">x.y</span><span class="red">)</span>[z]()</code> evaluates <code>x.y</code> first, then uses the result as the target of the method call. Note that <code>x.y[z].Call()</code> does not have this limitation since it is evaluated the same as <code>(x.y[z]).Call()</code>.</li></ul>
<h3 id="Usage_Freeing_Objects">Freeing Objects</h3>
<p>Scripts do not free objects explicitly. When the last reference to an object is released, the object is freed automatically. A reference stored in a variable is released automatically when that variable is assigned some other value. Por ejemplo:</p>
<pre>obj := {} <em>; Creates an object.</em>
obj := "" <em>; Releases the last reference, and therefore frees the object.</em></pre>
<p>Similarly, a reference stored in a field of another object is released when that field is assigned some other value or removed from the object. This also applies to arrays, which are actually objects.</p>
<pre>arr := [{}] <em>; Creates an array containing an object.</em>
arr[1] := {} <em>; Creates a second object, implicitly freeing the first object.</em>
arr.RemoveAt(1) <em>; Removes and frees the second object.</em></pre>
<p id="Circular_References">Because all references to an object must be released before the object can be freed, objects containing circular references aren't freed automatically. For instance, if <code>x.child</code> refers to <code>y</code> and <code>y.parent</code> refers to <code>x</code>, clearing <code>x</code> and <code>y</code> is not sufficient since the parent object still contains a reference to the child and vice versa. To resolve this situation, remove the circular reference.</p>
<pre>
x := {}, y := {} <em>; Create two objects.</em>
x.child := y, y.parent := x <em>; Create a circular reference.</em>
y.parent := "" <em>; The circular reference must be removed before the objects can be freed.</em>
x := "", y := "" <em>; Without the above line, this would not free the objects.</em>
</pre>
<p>For more advanced usage and details, see <a href="#Reference_Counting">Reference Counting</a>.</p>
<h3 id="Usage_Remarks">Remarks</h3>
<h4 id="Remarks_Syntax">Syntax</h4>
<p>All types of objects support both array syntax (brackets) and object syntax (dots).</p>
<p>Additionally, object references can themselves be used in expressions:</p>
<ul>
<li>When an object reference is compared with some other value using <code>=</code>, <code>==</code>, <code>!=</code> or <code><></code>, they are considered equal only if both values are references to the same object.</li>
<li>Objects are always considered <i>true</i> when a boolean value is required, such as in <code>if obj</code>, <code>!obj</code> or <code>obj ? x : y</code>.</li>
<li>An object's address can be retrieved using the <code>&</code>address-of operator. This uniquely identifies the object from the point of its creation to the moment its last reference is <a href="#Refs">released</a>.</li>
</ul>
<p>If an object is used in any context where an object is not expected, it is treated as an empty string. For example, <code>MsgBox %object%</code> shows an empty MsgBox and <code>object + 1</code> yields an empty string. Do not rely on this behaviour as it may change.</p>
<p>When a method-call is followed immediately by an assignment operator, it is equivalent to setting a property with parameters. For example, the following are equivalent:</p>
<pre>obj.item(x) := y
obj.item[x] := y</pre>
<p id="cassign">Compound assignments such as <code>x.y += 1</code> and <code>--arr[1]</code> are supported.</p>
<p><span class="ver">[v1.1.20+]:</span> Parameters can be omitted when getting or setting properties. For example, <code>x[,2]</code>. Scripts can utilize this by defining default values for parameters in <a href="#Custom_Classes_property">properties</a> and <a href="#Meta_Functions">meta-functions</a>. The method name can also be completely omitted, as in <code>x[](a)</code>. Scripts can utilize this by defining a default value for the __Call <a href="#Meta_Functions">meta-function</a>'s first parameter, since it is not otherwise supplied with a value. Note that this differs from <code>x.(a)</code>, which is equivalent to <code>x[""](a)</code>. If the property or method name is omitted when invoking a COM object, its "default member" is invoked.</p>
<h4 id="Keys">Keys</h4>
<p>Some limitations apply to which values can be used as keys in objects created with <code>[]</code>, <code>{}</code> or the <code>new</code> operator:</p>
<ul>
<li>Integer keys are stored using the native signed integer type. AutoHotkey 32-bit supports integer keys in the range -2147483648 to 2147483647, and truncates values outside that range. AutoHotkey supports 64-bit integers, but only AutoHotkey 64-bit supports the full range as keys in an object.</li>
<li>The string format of integer values is not retained. For example, AutoHotkey v1 produces two different strings for <code>0x10</code> and <code>16</code> (unlike <a href="https://www.autohotkey.com/v2/">AutoHotkey v2</a>), but <code>x[0x10]</code>, <code>x[16]</code> and <code>x[00016]</code> are equivalent as only the numeric value is used.</li>
<li>Numeric strings that do not contain a decimal point are converted to pure integers, so are subject to the limitations described above. Numeric strings outside the 64-bit range may produce inconsistent results.</li>
<li>Quoted literal strings are considered purely non-numeric in v1.x, so <code>x[1]</code> and <code>x["1"]</code> are <i>not</i> equivalent. Additionally, if a quoted literal string is concatenated with another value (as in <code>"0x" x</code>), the result is treated as purely non-numeric. However, this does not apply to variables, so <code>x[1]</code> and <code>x[y:="1"]</code> are equivalent. This issue will be resolved in <a href="https://www.autohotkey.com/v2/">AutoHotkey v2</a>, so scripts should avoid using quoted numeric literals as keys.</li>
<li>Floating-point numbers are not supported as keys - instead they are converted to strings. In v1.x, floating-point literals retain their original format whereas pure floating-point numbers (such as the result of <code>0+1.0</code> or <code>Sqrt(y)</code>) are forced into the current <a href="lib/SetFormat.htm">float format</a>. For consistency and clarity, scripts should avoid using floating-point literals as keys.</li>
<li id="base-key">By default, the string key "base" corresponds to the object's <a href="lib/Object.htm#Base">base</a> property, so cannot be used for storing ordinary values with a normal assignment. However, any property can be overridden by storing a value by some other means, such as <code><a href="lib/Object.htm#RawSet">ObjRawSet</a>(Object, "base", "")</code> or <code><a href="lib/Object.htm#SetCapacity">Object.SetCapacity</a>("base", 0)</code>. Once this is done, the key "base" acts like any other string.</li>
<li>Although <a href="lib/Object.htm">built-in method</a> names such as "Length" can be used as keys, storing a value will prevent the corresponding method from being called (unless that value is a reference to the appropriate function, such as <em>ObjLength</em>).</li>
</ul>
<h2 id="Extended_Usage">Extended Usage</h2>
<h3 id="Function_References">Function References <span class="ver">[v1.1.00+]</span></h3>
<p>If the variable <i>func</i> contains a function name, the function can be called one of two ways: <code>%func%()</code> or <code>func.()</code>. However, this requires the function name to be resolved each time, which is inefficient if the function is called more than once. To improve performance, the script can retrieve a reference to the function and store it for later use:</p>
<pre>Func := Func("MyFunc")</pre>
<p>A function can be called by reference using the following syntax:</p>
<pre>
RetVal := %Func%(<i>Params</i>) <em>; Requires <span class="ver">[v1.1.07+]</span></em>
RetVal := Func.Call(<i>Params</i>) <em>; Requires <span class="ver">[v1.1.19+]</span></em>
RetVal := Func.(<i>Params</i>) <em>; Not recommended</em>
</pre>
<p>For details about additional properties of function references, see <a href="lib/Func.htm">Func Object</a>.</p>
<span id="JaggedArrays"></span><h3 id="Usage_Arrays_of_Arrays">Arrays of Arrays</h3>
<p>AutoHotkey supports "multi-dimensional" arrays by transparently storing arrays inside other arrays. For example, a table could be represented as an array of rows, where each row is itself an array of columns. In that case, the content of column <code>y</code> of row <code>x</code> can be set using either of the methods below:</p>
<pre>table[x][y] := content <em>; A</em>
table[x, y] := content <em>; B</em></pre>
<p>If <code>table[x]</code> does not exist, <span class="Code"><em>A</em></span> and <span class="Code"><em>B</em></span> differ in two ways:</p>
<ul>
<li><span class="Code"><em>A</em></span> fails whereas <span class="Code"><em>B</em></span> automatically creates an object and stores it in <code>table[x]</code>.</li>
<li>If <code>table</code>'s <a href="#Custom_Objects">base</a> defines <a href="#Meta_Functions">meta-functions</a>, they are invoked as follows:
<pre>table.base.__Get(table, x)<span class="dull">[y] := content</span> <em>; A</em>
table.base.__Set(table, x, y, content) <em>; B</em></pre>
Consequently, <span class="Code"><em>B</em></span> allows the object to define custom behaviour for the overall assignment.</li>
</ul>
<p>Multi-dimensional assignments such as <code>table[a, b, c, d] := value</code> are handled as follows:</p>
<ul>
<li>If there is only one key remaining, perform the assignment and return. Otherwise:</li>
<li>Search the object for the first key in the list.</li>
<li>If a non-object is found, fail.</li>
<li>If an object is not found, create one and store it.</li>
<li>Recursively invoke the sub-object, passing the remaining keys and value - repeat from the top.</li>
</ul>
<p>This behaviour only applies to script-created objects, not more specialized types of objects such as COM objects or COM arrays.</p>
<span id="FuncArrays"></span><h3 id="Usage_Arrays_of_Functions">Arrays of Functions</h3>
<p>An array of functions is simply an array containing function names or references. Por ejemplo:</p>
<pre>array := [Func("FirstFunc"), Func("SecondFunc")]
<em>; Call each function, passing "foo" as a parameter:</em>
Loop 2
array[A_Index].Call("foo")
<em>; Call each function, implicitly passing the array itself as a parameter:</em>
Loop 2
array[A_Index]()
FirstFunc(param) {
MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
}
SecondFunc(param) {
MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
}</pre>
<p>For backward-compatibility, the second form will not pass <i>array</i> as a parameter if <code>array[A_Index]</code> contains a function name instead of a function reference. However, if <code>array[A_Index]</code> is <a href="#Custom_Objects">inherited</a> from <code>array.base[A_Index]</code>, <i>array</i> will be passed as a parameter.</p>
<h2 id="Custom_Objects">Custom Objects</h2>
<p>Objects created by the script do not need to have any predefined structure. Instead, each object can inherit properties and methods from its <em>base</em> object (otherwise known as a "prototype" or "class"). Properties and methods can also be added to (or removed from) an object at any time, and those changes will affect any and all derived objects. For more complex or specialized situations, a base object can override the standard behaviour of any objects derived from it by defining <a href="#Meta_Functions"><i>meta-functions</i></a>.</p>
<p><em>Base</em> objects are just ordinary objects, and are typically created one of two ways:</p>
<pre>class baseObject {
static foo := "bar"
}
<em>; OR</em>
baseObject := {foo: "bar"}</pre>
<p>To create an object derived from another object, scripts can assign to the <a href="lib/Object.htm#Base">base property</a> or use the <a href="#Custom_NewDelete"><code>new</code> keyword</a>:</p>
<pre>obj1 := Object(), obj1.base := baseObject
obj2 := {base: baseObject}
obj3 := new baseObject
MsgBox % obj1.foo " " obj2.foo " " obj3.foo</pre>
<p>It is possible to reassign an object's <em>base</em> at any time, effectively replacing all of the properties and methods that the object inherits.</p>
<h3 id="Custom_Prototypes">Prototypes</h3>
<p>Prototype or <em>base</em> objects are constructed and manipulated the same as any other object. For example, an ordinary object with one property and one method might be constructed like this:</p>
<pre><em>; Create an object.</em>
thing := {}
<em>; Store a value.</em>
thing.foo := "bar"
<em>; Create a method by storing a function reference.</em>
thing.test := Func("thing_test")
<em>; Call the method.</em>
thing.test()
thing_test(this) {
MsgBox % this.foo
}</pre>
<p>When <code>thing.test()</code> is called, <i>thing</i> is automatically inserted at the beginning of the parameter list. However, for backward-compatibility, this does not occur when a function is stored by name (rather than by reference) directly in the object (rather than being inherited from a base object). By convention, the function is named by combining the "type" of object and the method name.</p>
<p>An object is a <i>prototype</i> or <i>base</i> if another object derives from it:</p>
<pre>other := {}
other.base := thing
other.test()</pre>
<p>In this case, <i>other</i> inherits <i>foo</i> and <i>test</i> from <i>thing</i>. This inheritance is dynamic, so if <code>thing.foo</code> is modified, the change will be reflected by <code>other.foo</code>. If the script assigns to <code>other.foo</code>, the value is stored in <i>other</i> and any further changes to <code>thing.foo</code> will have no effect on <code>other.foo</code>. When <code>other.test()</code> is called, its <i>this</i> parameter contains a reference to <i>other</i> instead of <i>thing</i>.</p>
<h3 id="Custom_Classes">Classes <span class="ver">[v1.1.00+]</span></h3>
<p>At its root, a "class" is a set or category of things having some property or attribute in common. Since a <a href="#Custom_Objects">base</a> or <a href="#Custom_Prototypes">prototype</a> object defines properties and behaviour for set of objects, it can also be called a <em>class</em> object. For convenience, base objects can be defined using the "class" keyword as shown below:</p>
<pre>class ClassName extends BaseClassName
{
InstanceVar := Expression
static ClassVar := Expression
class NestedClass
{
...
}
Method()
{
...
}
Property[] <em>; Brackets are optional</em>
{
get {
return ...
}
set {
return ... := value
}
}
}
</pre>
<p>When the script is loaded, this constructs an object and stores it in the global (or <span class="ver">[in v1.1.05+]</span> <a href="Functions.htm#SuperGlobal">super-global</a>) variable <i>ClassName</i>. To reference this class inside a <a href="Functions.htm#ForceLocal">force-local</a> function (or an assume-local or assume-static function prior to <span class="ver">[v1.1.05]</span>), a declaration such as <code>global ClassName</code> is required. If <code>extends BaseClassName</code> is present, <i>BaseClassName</i> must be the full name of another class (but as of <span class="ver">[v1.1.11]</span>, the order that they are defined in does not matter). The full name of each class is stored in <code><i>object</i>.__Class</code>.</p>
<p>Because the class is referenced via a variable, the class name cannot be used to both reference the class and create a separate variable (such as to hold an instance of the class) in the same context. For example, <code>box := new Box</code> would replace the class object in <em>Box</em> with an instance of itself. <span class="ver">[v1.1.27+]:</span> <a href="lib/_Warn.htm#ClassOverwrite">#Warn ClassOverwrite</a> enables a warning to be shown at load time for each attempt to overwrite a class.</p>
<p>Within this documentation, the word "class" on its own usually means a class object constructed with the <code>class</code> keyword.</p>
<p>Class definitions can contain variable declarations, method definitions and nested class definitions.</p>
<h4 id="Custom_Classes_var">Instance Variables <span class="ver">[v1.1.01+]</span></h4>
<p>An <em>instance variable</em> is one that each instance of the class (that is, each object derived from the class) has its own copy of. They are declared like normal assignments, but the <code>this.</code> prefix is omitted (only directly within the class body):</p>
<pre>InstanceVar := Expression</pre>
<p>These declarations are evaluated each time a new instance of the class is created with the <a href="#Custom_NewDelete">new</a> keyword. The method name <code>__Init</code> is reserved for this purpose, and should not be used by the script. The <a href="#Custom_NewDelete">__New()</a> method is called after all such declarations have been evaluated, including those defined in base classes. <em>Expression</em> can access other instance variables and methods via <code>this</code>, but all other variable references are assumed to be global.</p>
<p>To access an instance variable (even within a method), always specify the target object; for example, <code><b>this</b>.InstanceVar</code>.</p>
<p><span class="ver">[v1.1.08+]:</span> Declarations like <code>x.y := z</code> are also supported, provided that <code>x</code> was previously declared in this class. For example, <code>x := {}, x.y := 42</code> declares <code>x</code> and also initializes <code>this.x.y</code>.</p>
<h4 id="Custom_Classes_staticvar">Static/Class Variables <span class="ver">[v1.1.00.01+]</span></h4>
<p>Static/class variables belong to the class itself, but can be inherited by derived objects (including sub-classes). They are declared like instance variables, but using the static keyword:</p>
<pre>static ClassVar := Expression</pre>
<p>Static declarations are evaluated only once, before the <a href="Scripts.htm#auto">auto-execute section</a>, in the order they appear in the script. Each declaration stores a value in the class object. Any variable references in <i>Expression</i> are assumed to be global.</p>
<p>To assign to a class variable, always specify the class object; for example, <code><b>ClassName</b>.ClassVar := Value</code>. If an object <em>x</em> is derived from <em>ClassName</em> and <em>x</em> itself does not contain the key "ClassVar", <code>x.ClassVar</code> may also be used to dynamically retrieve the value of <code>ClassName.ClassVar</code>. However, <code>x.ClassVar := y</code> would store the value in <em>x</em>, not in <em>ClassName</em>.</p>
<p><span class="ver">[v1.1.08+]:</span> Declarations like <code>static x.y := z</code> are also supported, provided that <code>x</code> was previously declared in this class. For example, <code>static x := {}, x.y := 42</code> declares <code>x</code> and also initializes <code><i>ClassName</i>.x.y</code>.</p>
<h4 id="Custom_Classes_class">Nested Classes</h4>
<p>Nested class definitions allow a class object to be stored inside another class object rather than a separate global variable. In the example above, <code>class NestedClass</code> constructs an object and stores it in <code>ClassName.NestedClass</code>. Sub-classes could inherit <em>NestedClass</em> or override it with their own nested class (in which case <code>new this.NestedClass</code> could be used to instantiate whichever class is appropriate).</p>
<pre>
class NestedClass
{
...
}
</pre>
<h4 id="Custom_Classes_method">Methods</h4>
<p>Method definitions look identical to function definitions. Each method has a hidden parameter named <code>this</code>, which typically contains a reference to an object derived from the class. However, it could contain a reference to the class itself or a derived class, depending on how the method was called. Methods are stored <a href="#Function_References">by reference</a> in the class object.</p>
<pre>
Method()
{
...
}
</pre>
<p id="Custom_Classes_base">Inside a method, the pseudo-keyword <code>base</code> can be used to access the super-class versions of methods or properties which are overridden in a derived class. For example, <code>base.Method()</code> in the class defined above would call the version of <em>Method</em> which is defined by <em>BaseClassName</em>. <a href="#Meta_Functions">Meta-functions</a> are not called; otherwise, <code>base.Method()</code> behaves like <code>BaseClassName.Method.Call(this)</code>. That is,</p>
<ul>
<li><code>base.Method()</code> always invokes the base of the class where the current method was defined, even if <code>this</code> is derived from a <em>sub-class</em> of that class or some other class entirely.</li>
<li><code>base.Method()</code> implicitly passes <code>this</code> as the first (hidden) parameter.</li>
</ul>
<p><code>base</code> only has special meaning if followed by a dot <code>.</code> or brackets <code>[]</code>, so code like <code>obj := base, obj.Method()</code> will not work. Scripts can disable the special behaviour of <i>base</i> by assigning it a non-empty value; however, this is not recommended. Since the variable <i>base</i> must be empty, performance may be reduced if the script omits <a href="lib/_NoEnv.htm">#NoEnv</a>.</p>
<h4 id="Custom_Classes_property">Properties <span class="ver">[v1.1.16+]</span></h4>
<p>Property definitions allow a method to be executed whenever the script gets or sets a specific key.</p>
<pre>Property[]
{
get {
return ...
}
set {
return ... := value
}
}</pre>
<p><em>Property</em> is simply the name of the property, which will be used to invoke it. For example, <code>obj.Property</code> would call <em>get</em> while <code>obj.Property := value</code> would call <em>set</em>. Within <em>get</em> or <em>set</em>, <code>this</code> refers to the object being invoked. Within <em>set</em>, <code>value</code> contains the value being assigned.</p>
<p>Parameters can be passed by enclosing them in square brackets to the right of the property name, both when defining the property and when calling it. Aside from using square brackets, parameters of properties are defined the same way as parameters of methods - optional, ByRef and variadic parameters are supported.</p>
<p>The return value of <em>get</em> or <em>set</em> becomes the result of the sub-expression which invoked the property. For example, <code>val := obj.Property := 42</code> stores the return value of <em>set</em> in <code>val</code>.</p>
<p>Each class can define one or both halves of a property. If a class overrides a property, it can use <code><a href="#Custom_Classes_base">base.Property</a></code> to access the property defined by its base class. If <em>get</em> or <em>set</em> is not defined, it can be handled by a base class. If <em>set</em> is not defined and is not handled by a meta-function or base class, assigning a value stores it in the object, effectively disabling the property.</p>
<p>Internally, <em>get</em> and <em>set</em> are two separate methods, so cannot share variables (except by storing them in <code>this</code>).</p>
<p><a href="#Meta_Functions">Meta-functions</a> provide a broader way of controlling access to properties and methods of an object, but are more complicated and error-prone.</p>
<h3 id="Custom_NewDelete">Construction and Destruction</h3>
<p>Whenever a derived object is created with the <code>new</code> keyword <span class="ver">[requires v1.1.00+]</span>, the <code>__New</code> method defined by its base object is called. This method can accept parameters, initialize the object and override the result of the <code>new</code> operator by returning a value. When an object is destroyed, <code>__Delete</code> is called. Por ejemplo:</p>
<pre>m1 := new GMem(0, 20)
m2 := {base: GMem}.__New(0, 30)
class GMem
{
__New(aFlags, aSize)
{
this.ptr := DllCall("GlobalAlloc", "UInt", aFlags, "Ptr", aSize, "Ptr")
if !this.ptr
return ""
MsgBox % "New GMem of " aSize " bytes at address " this.ptr "."
return this <em>; This line can be omitted when using the 'new' operator.</em>
}
__Delete()
{
MsgBox % "Delete GMem at address " this.ptr "."
DllCall("GlobalFree", "Ptr", this.ptr)
}
}</pre>
<p>__Delete is not called for any object which has the key "__Class". <a href="#Custom_Classes">Class objects</a> have this key by default.</p>
<p>If the class has a super-class which defines these methods, <code>base.__New()</code> (with parameters as appropriate) and <code>base.__Delete()</code> should typically be called. Otherwise, only the most derived definition of the method is called, excluding any definition within the target object itself.</p>
<p><span class="ver">[v1.1.28+]:</span> If an exception or runtime error is thrown while __Delete is executing and is not handled within __Delete, it acts as though __Delete was called from a new <a href="misc/Threads.htm">thread</a>. That is, an error dialog is displayed and __Delete returns, but the thread does not exit (unless it was already exiting). Prior to v1.1.28, unhandled exceptions caused inconsistent behavior.</p>
<p>If the script is directly terminated by any means, including the tray menu, <a href="lib/ExitApp.htm">ExitApp</a>, or <a href="lib/Exit.htm">Exit</a> (when the script is not <a href="lib/_Persistent.htm">persistent</a>), any functions which have yet to return do not get the chance to do so. Therefore, any objects referenced by local variables of those functions are not released, so __Delete is not called.</p>
<p>When the script exits, objects contained by global and static variables are released automatically in an arbitrary, implementation-defined order. When __Delete is called during this process, some global or static variables may have already been released, but any references contained by the object itself are still valid. It is therefore best for __Delete to be entirely self-contained, and not rely on any global or static variables.</p>
<h3 id="Meta_Functions">Meta-Functions</h3>
<pre class="Syntax">
<strong>Method syntax:</strong>
class <i>ClassName</i> {
__Get([Key, Key2, ...])
__Set([Key, Key2, ...], Value)
__Call(Name [, Params...])
}
<strong>Function syntax:</strong>
<i>MyGet</i>(this [, Key, Key2, ...])
<i>MySet</i>(this [, Key, Key2, ...], Value)
<i>MyCall</i>(this, Name [, Params...])
<i>ClassName</i> := { __Get: Func("<i>MyGet</i>"), __Set: Func("<i>MySet</i>"), __Call: Func("<i>MyCall</i>") }
</pre>
<p>Meta-functions define what happens when a key is requested but not found within the target object. For example, if <code>obj.key</code> has not been assigned a value, it invokes the <i>__Get</i> meta-function. Similarly, <code>obj.key := value</code> invokes <i>__Set</i> and <code>obj.key()</code> invokes <i>__Call</i>. These meta-functions (or methods) would need to be defined in <code>obj.base</code>, <code>obj.base.base</code> or such.</p>
<p>Meta-functions are generally defined like methods, but do not follow the same rules (except when called explicitly by the script). They must be defined in a base object; any definition in the target object itself is ignored. Each definition of __Get, __Set and __Call applicable to the target object is called automatically according to the rules below, and should not call <code>base.__Get(key)</code> or similar. <a href="#Custom_NewDelete">__New</a> and <a href="#Custom_NewDelete">__Delete</a> must be defined in a base object, but otherwise behave like methods.</p>
<p class="note"><strong>Note:</strong> AutoHotkey v2 replaces meta-functions with more conventional methods.</p>
<p>When the script gets, sets or calls a key which does not exist within the target object, the base object is invoked as follows:</p>
<ul class="list_of_p">
<li>If this base object defines the appropriate meta-function, call it. If the meta-function explicitly <code>return</code>s, use the return value as the result of the operation (whatever caused the meta-function to be called) and return control to the script. Otherwise, continue as described below.
<p><i>Set</i>: If the meta-function handled an assignment, it should return the value which was assigned. This allows assignments to be chained, as in <code>a.x := b.y := z</code>. The return value may differ from the original value of <code>z</code> (for instance, if restrictions are imposed on which values can be assigned).</p></li>
<li>Search for a matching key in the base object's own fields.</li>
<li><span class="ver">[v1.1.16+]:</span> If a key corresponding to a property is found and it implements <em>get</em> or <em>set</em> (as appropriate), invoke the property and return. If this is a method call, invoke <em>get</em>.</li>
<li>If no key was found, recursively invoke this base object's own base (apply each of these steps to it, starting at the top of this list). If we're not finished yet, search this base object for a matching key again in case one was added by a meta-function.
<p>Due to backward-compatibility, this step is performed for <em>set</em> operations even if a key was found (unless it defines a property which implements <em>set</em>).</p></li>
<li>If multiple parameters were given for <i>get</i> or <i>set</i> and a key was found, check its value. If that value is an object, handle the remaining parameters by invoking it, and do nothing further.</li>
<li>If a key was found,<br>
<i>Get</i>: Return the value.<br>
<i>Call</i>: Attempt to call the value, passing the target object as the first parameter (<code>this</code>). The value should be a function name or a <a href="misc/Functor.htm">function object</a>.</li>
</ul>
<p>If a meta-function stores a matching key in the object but does not <code>return</code>, the behaviour is the same as if the key initially existed in the object. For an example using __Set, see <a href="#Subclassing_aoa">Sub-classing Arrays of Arrays</a>.</p>
<p>If the operation still hasn't been handled, check if this is a built-in method or property:</p>
<ul>
<li><i>Get</i>: If the key is "base", return the object's base.</li>
<li><i>Set</i>: If the key is "base", set the object's base (or remove it if the value isn't an object).</li>
<li><i>Call</i>: Call a <a href="lib/Object.htm">built-in method</a> if applicable.</li>
</ul>
<p>If the operation still hasn't been handled,</p>
<ul>
<li><i>Get</i> and <i>Call</i>: Return an empty string.</li>
<li><i>Set</i>: If only one key parameter was given, store the key and value in the target object and return the assigned value. If multiple parameters were given, create a new object and store it using the first parameter as a key, then handle the remaining parameters by invoking the new object. (See <a href="#Usage_Arrays_of_Arrays">Arrays of Arrays</a>.)</li>
</ul>
<p><b>Known limitation:</b></p>
<ul><li>Using <code>return</code> without a value is equivalent to <code>return ""</code>. This may be changed in a future version so that <code>return</code> can be used to "escape" from a meta-function without overriding the default behaviour.</li></ul>
<h4 id="Dynamic_Properties">Dynamic Properties</h4>
<p><a href="#Custom_Classes_property">Property syntax</a> can be used to define properties which compute a value each time they are evaluated, but each property must be known in advance and defined individually in the script. By contrast, <em>__Get</em> and <em>__Set</em> can be used to implement properties which aren't known by the script.</p>
<p>For example, a "proxy" object could be created which sends requests for properties over the network (or through some other channel). A remote server would send back a response containing the value of the property, and the proxy would return the value to its caller. Even if the name of each property was known in advance, it would not be logical to define each property individually in the proxy class since every property does the same thing (send a network request). Meta-functions receive the property name as a parameter, so are a good solution for this problem.</p>
<p>Another use of <em>__Get</em> and <em>__Set</em> is to implement a set of related properties which share code. In the example below they are used to implement a "Color" object with R, G, B and RGB properties, where only the RGB value is actually stored:</p>
<pre>red := new Color(0xff0000), red.R -= 5
cyan := new Color(0), cyan.G := 255, cyan.B := 255
MsgBox % "red: " red.R "," red.G "," red.B " = " red.RGB
MsgBox % "cyan: " cyan.R "," cyan.G "," cyan.B " = " cyan.RGB
class Color
{
__New(aRGB)
{
this.RGB := aRGB
}
static Shift := {R:16, G:8, B:0}
__Get(aName)
{
<em>; <span class="red">NOTE:</span> Using this.Shift here would cause an infinite loop!</em>
shift := Color.Shift[aName] <em>; Get the number of bits to shift.</em>
if (shift != "") <em>; Is it a known property?</em>
return (this.RGB >> shift) & 0xff
<em>; <span class="red">NOTE:</span> Using 'return' here would break this.RGB.</em>
}
__Set(aName, aValue)
{
if ((shift := Color.Shift[aName]) != "")
{
aValue &= 255 <em>; Truncate it to the proper range.
; Calculate and store the new RGB value.</em>
this.RGB := (aValue << shift) | (this.RGB & ~(0xff << shift))
<em>; 'Return' must be used to indicate a new key-value pair should not be created.
; This also defines what will be stored in the 'x' in 'x := clr[name] := val':</em>
return aValue
}
<em>; <span class="red">NOTE:</span> Using 'return' here would break this.stored_RGB and this.RGB.</em>
}
<em>; Meta-functions can be mixed with properties:</em>
RGB {
get {
<em>; Return it in hex format:</em>
return format("0x{:06x}", this.stored_RGB)
}
set {
return this.stored_RGB := value
}
}
}</pre>
<p>However, in this case <a href="#Custom_Classes_property">Property syntax</a> could have been used instead, where code is shared by simply having each property call a central method. It is better to avoid using meta-functions where possible due to the high risk of misuse (see the notes in red above).</p>
<h4 id="Objects_as_Functions">Objects as Functions</h4>
<p>For an outline of how to create objects which can act as functions, see <a href="misc/Functor.htm#User-Defined">Function Objects</a>.</p>
<p>A function object can also act as a meta-function, such as to define dynamic properties similar to those in the previous section. Although it is recommended to use <a href="#Custom_Classes_property">property syntax</a> instead, the example below shows the potential of meta-functions for implementing new concepts or behaviour, or changing the structure of the script.</p>
<pre><em>; This example requires the <a href="misc/Functor.htm#class_FunctionObject">FunctionObject class</a> in order to work.</em>
blue := new Color(0x0000ff)
MsgBox % blue.R "," blue.G "," blue.B
class Properties extends FunctionObject
{
Call(aTarget, aName, aParams*)
{
<em>; If this Properties object contains a definition for this half-property, call it.</em>
if ObjHasKey(this, aName)
return this[aName].Call(aTarget, aParams*)
}
}
class Color
{
__New(aRGB)
{
this.RGB := aRGB
}
class __Get extends Properties
{
R() {
return (this.RGB >> 16) & 255
}
G() {
return (this.RGB >> 8) & 255
}
B() {
return this.RGB & 255
}
}
<em>;...</em>
}</pre>
<h4 id="Subclassing_aoa">Sub-classing Arrays of Arrays</h4>
<p>When a <a href="#Usage_Arrays_of_Arrays">multi-parameter assignment</a> such as <code>table[x, y] := content</code> implicitly causes a new object to be created, the new object ordinarily has no base and therefore no custom methods or special behaviour. <code>__Set</code> may be used to initialize these objects, as demonstrated below.</p>
<pre>x := {base: {addr: Func("x_Addr"), __Set: Func("x_Setter")}}
<em>; Assign value, implicitly calling x_Setter to create sub-objects.</em>
x[1,2,3] := "..."
<em>; Retrieve value and call example method.</em>
MsgBox % x[1,2,3] "`n" x.addr() "`n" x[1].addr() "`n" x[1,2].addr()
x_Setter(x, p1, p2, p3) {
x[p1] := new x.base
}
x_Addr(x) {
return &x
}</pre>
<p>Since <code>x_Setter</code> has four mandatory parameters, it will only be called when there are two or more key parameters. When the assignment above occurs, the following takes place:</p>
<ul>
<li><code>x[1]</code> does not exist, so <code>x_Setter(x,1,2,3)</code> is called (<code>"..."</code> is not passed as there are too few parameters).
<ul>
<li><code>x[1]</code> is assigned a new object with the same base as <code>x</code>.</li>
<li>No value is returned – the assignment continues.</li>
</ul></li>
<li><code>x[1][2]</code> does not exist, so <code>x_Setter(x[1],2,3,"...")</code> is called.
<ul>
<li><code>x[1][2]</code> is assigned a new object with the same base as <code>x[1]</code>.</li>
<li>No value is returned – the assignment continues.</li>
</ul></li>
<li><code>x[1][2][3]</code> does not exist, but since <code>x_Setter</code> requires four parameters and there are only three (<code>x[1][2], 3, "..."</code>), it is not called and the assignment completes as normal.</li>
</ul>
<h2 id="Default_Base_Object">Default Base Object</h2>
<p>When a non-object value is used with object syntax, the <i>default base object</i> is invoked. This can be used for debugging or to globally define object-like behaviour for strings, numbers and/or variables. The default base may be accessed by using <code>.base</code> with any non-object value; for instance, <code>"".base</code>. Although the default base cannot be <i>set</i> as in <code>"".base := Object()</code>, the default base may itself have a base as in <code>"".base.base := Object()</code>.</p>
<h3 id="Automatic_Var_Init">Automatic Var Init</h3>
<p>When an empty variable is used as the target of a <i>set</i> operation, it is passed directly to the __Set meta-function, giving it opportunity to insert a new object into the variable. For brevity, this example does not support multiple parameters; it could, by using a <a href="Functions.htm#Variadic">variadic function</a>.</p>
<pre>"".base.__Set := Func("Default_Set_AutomaticVarInit")
empty_var.foo := "bar"
MsgBox % empty_var.foo
Default_Set_AutomaticVarInit(ByRef var, key, value)
{
if (var = "")
var := Object(key, value)
}</pre>
<h3 id="Pseudo_Properties">Pseudo-Properties</h3>
<p>Object "syntax sugar" can be applied to strings and numbers.</p>
<pre>"".base.__Get := Func("Default_Get_PseudoProperty")
"".base.is := Func("Default_is")
MsgBox % A_AhkPath.length " == " StrLen(A_AhkPath)
MsgBox % A_AhkPath.length.is("integer")
Default_Get_PseudoProperty(nonobj, key)
{
if (key = "length")
return StrLen(nonobj)
}
Default_is(nonobj, type)
{
if nonobj is %type%
return true
return false
}</pre>
<p>Note that built-in functions may also be used, but in this case the parentheses cannot be omitted:</p>
<pre>"".base.length := Func("StrLen")
MsgBox % A_AhkPath.length() " == " StrLen(A_AhkPath)</pre>
<h3 id="Default__Warn">Debugging</h3>
<p>If allowing a value to be treated as an object is undesirable, a warning may be shown whenever a non-object value is invoked:</p>
<pre>"".base.__Get := "".base.__Set := "".base.__Call := Func("Default__Warn")
empty_var.foo := "bar"
x := (1 + 1).is("integer")
Default__Warn(nonobj, p1="", p2="", p3="", p4="")
{
ListLines
MsgBox A non-object value was improperly invoked.`n`nSpecifically: %nonobj%
}</pre>
<h2 id="Implementation">Implementation</h2>
<span id="Refs"></span><h3 id="Reference_Counting">Reference-Counting</h3>
<p>AutoHotkey uses a basic reference-counting mechanism to automatically free the resources used by an object when it is no longer referenced by the script. Script authors should not invoke this mechanism explicitly, except when dealing directly with unmanaged <a href="#Implementation_Pointers">pointers to objects</a>.</p>
<p>Currently in AutoHotkey v1.1, temporary references created within an expression (but not stored anywhere) are released immediately after use. For example, <code>Fn(&{})</code> passes an invalid address to the function, because the temporary reference returned by <code>{}</code> is released immediately after the <a href="Variables.htm#amp">address-of</a> operator is evaluated.</p>
<p>To run code when the last reference to an object is being released, implement the <a href="#Custom_NewDelete">__Delete</a> meta-function.</p>
<p><b>Known Limitations:</b></p>
<ul>
<li>Circular references must be broken before an object can be freed. For details and an example, see <a href="#Circular_References">Freeing Objects</a>.</li>
<li>Although references in static and global variables are released automatically when the program exits, references in non-static local variables or on the expression evaluation stack are not. These references are only released if the function or expression is allowed to complete normally.</li>
</ul>
<p>Although memory used by the object is reclaimed by the operating system when the program exits, <a href="#Custom_NewDelete">__Delete</a> will not be called unless all references to the object are freed. This can be important if it frees other resources which are not automatically reclaimed by the operating system, such as temporary files.</p>
<span id="AddressCast"></span><h3 id="Implementation_Pointers">Pointers to Objects</h3>
<p>In some rare cases it may be necessary to pass an object to external code via DllCall() or store it in a binary data structure for later retrieval. An object's address can be retrieved via <code>address := &object</code>; however, this effectively makes two references to the object, but the program only knows about the one in <em>object</em>. If the last <em>known</em> reference to the object was released, the object would be deleted. Therefore, the script must inform the object that it has gained a reference. There are two ways to do this:</p>
<pre><em>; Method #1: Explicitly increment the reference count.</em>
address := &object
<a href="lib/ObjAddRef.htm">ObjAddRef</a>(address)
<em>; Method #2: Use Object(), which increments the reference count and returns an address.</em>
address := Object(object)</pre>
<p>This function can also be used to convert an address back into a reference:</p>
<pre>object := Object(address)</pre>
<p>Either way, the script must also inform the object when it is finished with that reference:</p>
<pre><em>; Decrement the object's reference count to allow it to be freed:</em>
<a href="lib/ObjAddRef.htm">ObjRelease</a>(address)
</pre>
<p>Generally each new copy of an object's address should be treated as another reference to the object, so the script should call ObjAddRef() when it gains a copy and ObjRelease() immediately before losing one. For example, whenever an address is copied via something like <code>x := address</code>, ObjAddRef() should be called. Similarly, when the script is finished with <em>x</em> (or is about to overwrite <em>x</em>'s value), it should call ObjRelease().</p>
<p>Note that the Object() function can be used even on objects which it did not create, such as <a href="lib/ComObjCreate.htm">COM objects</a> and <a href="lib/File.htm">File objects</a>.</p>
</body>
</html>