In the case of AutHotkey, most commonly an object. In this post, we will be talking about the syntax of making custom object classes that have methods, and how it works.wiktionary wrote:class /klɑːs/
n. A group, collection, category or set sharing characteristics or attributes.
Lets start off with the concept of functions in AutoHotkey. Originally in AutoHotkey, functions were accessible only by using their name. However, Lexikos got his hands on this and added a brand new way of accessing functions. This way, called Function References meant that you can save a (representation of a) function to a variable, and use that variable in place of the function name. To get a function reference, the new (actually pretty old now) MyReference := Func("MyFunctionName") syntax must be used. To call a function using a reference, RetVal := MyReference.Call(Params...) or RetVal := %MyReference%(Params...) must be used, though the latter is preferred since it also supports function names in addition to references.
Code: Select all
MyReference := Func("MyMsgBox")
%MyReference%("Hello World!")
MyMsgBox(MyString)
{
MsgBox, % MyString
}
Code: Select all
MyObj := {Key: Func("MyMsgBox")}
MyObj.Fish := Func("GoFishing")
Tmp := MyObj.Key, %Tmp%("Brb, Going fishin'")
; or MyObj.Key.Call("Brb, going fishin'")
MyObj.Fish.Call()
GoFishing()
{
; Lock the screen, we're going fishing
DllCall("LockWorkStation")
}
MyMsgBox(MyString)
{
MsgBox, % MyString
}
Code: Select all
MyObj := {MyMethod: Func("MyFunction"), Apples: 5}
MyObj.MyMethod("Johnny", 123)
MyFunction(this, Param1, Param2)
{
MsgBox, % Param1 " has " this.Apples " apples for " Param2 " customers"
}
Code: Select all
MyObj.MyMethod("Johnny", 123)
class MyObj
{
static Apples := 5
MyMethod(Param1, Param2)
{
MsgBox, % Param1 " has " this.Apples " apples for " Param2 " customers"
}
}
An instance of a class is just another object, with its base attribute set to the prototype (base) object. For example, you can create an instance with the code Instance := {base: MyClass} (though this doesn't call the instantiation routines). When the "base" attribute is set to something, AutoHotkey knows to pull information from there if it doesn't already exist in the instance. This applies to calling methods and retrieving attribute values, but not to setting attribute values.
The keyword new is used to easily create an instance of a class/base object, as well as automatically instantiate it. I'm not completely sure how it works internally, but here's to the best of my knowledge. It starts off by creating a new object as in the previous paragraph. Then it calls the (reserved by AutoHotkey, do not define it yourself) __Init() meta-function on it which handles things like non-static class variables. Once it finishes with that it checks for and calls the user defined __New initiation meta-function. If it exists and there is a return value, that is what is returned by new. If it doesn't exist or there isn't a return value, new returns the new instance.
Here is some code demonstrating the __New meta-function:
Code: Select all
MyInstance := new MyClass("MyDefault")
MyInstance.MyMethod()
class MyClass
{
__New(Default)
{
InputBox, OutputVar,, Enter a value for your new attribute,,,,,,,, %Default%
this.Attribute := OutputVar
}
MyMethod()
{
MsgBox, % this.Attribute
}
}
When AutoHotkey goes to find a attribute in your object, it first does the meta-function object.base.__Get check, then it moves on to "Does attribute exist in the object?". If it does, it uses it. If not it checks "Does it exist in the object's base?". If it does, it uses it. If not, it checks the base's base, and then the base's base's base, and so on until there are no more base objects.
When AutoHotkey goes to set a attribute in your object, it just creates the attribute in the original object. Consider closely what the following code will do:
Code: Select all
x := new y
MsgBox, % x.Attribute
y.Attribute := 3
MsgBox, % x.Attribute
x.Attribute -= 1
y.Attribute := 7
MsgBox, % x.Attribute
class Y
{
static Attribute := 5
}
Two sections ago I explained the use of the new keyword, and by extension the __New meta-function. A meta-function is a class method that doesn't get explicitly called, but gets called when something happens to the object. Meta-functions are called from the base object not the instance. If you create an object {__Call: Func("MyCallA"), base: {__Call: Func("MyCallB")}}, MyCallB would be used as the meta-function. Note that inheritance applies to meta-functions, so when object.base.Meta doesn't exist (or returns nothing), it checks for object.base.base.Meta, then object.base.base.base.Meta and so on.
There are several meta-functions, and they're listed below along with the context in which they are called:
- __New(Params...) - This gets called as MyObject.base.__New.(MyObject, "Banana", "Sandwich") when an an instance is created using new BaseObject("Banana", "Sandwich").
- __Delete() - This gets called as MyObject.base.__Delete.(MyObject) when the instance gets deleted, such as at the end of the script/function or when you do this to the last reference: MyInstance := AnythingElse
- __Get(Key) - This gets called as MyObject.base.__Get.(MyObject, "Pizza") when something does Var := MyObject.Pizza or Var := MyObject["Pizza"]
- __Set(Key, Value) - This gets called as MyObject.base.__Set.(MyObject, "Pizza", "Cheez") when something does MyObject.Pizza := "Cheez" or MyObject["Pizza"] := "Cheez"
- __Call(Name, Params...) - This gets called as MyObject.base.__Set.(MyObject, "DoSomething", "P1", "P2", "P3") when something does MyObject.DoSomething("P1", "P2", "P3"). Note that you can pass an arbitrary number of parameters to it. You can handle this using Variadic Functions, but that is outside the scope of this explanation.
- __Init() - This is reserved by AutoHotkey and should never be defined.
--- More coming ---
See post source bbcode and revisions here:
Spoiler