函数对象

"函数对象" 通常表示以下任何一项:

函数对象可用于以下情况:

要确定一个对象是否可被调用, 请使用以下方法之一:

用户自定义

用户定义的函数对象必须包含一个 "函数" 实现的 Call 方法定义.

class YourClassName {
    Call(a, b) {  ; 按需声明参数, 或 array*.
        ;...
        return c
    }
    ;...
}

这适用于 YourClassName实例, 例如由 YourClassName() 返回的对象. 用 static Call 代替 Call 将覆盖 YourClassName 本身被调用时的情况.

示例

下面的例子定义了一个可以被调用的函数数组; 当被调用时, 它依次调用数组中的每个元素.

class FuncArrayType extends Array {
    Call(params*) {
        ; 调用函数列表.
        for fn in this
            fn(params*)
    }
}

; 创建一个函数数组.
funcArray := FuncArrayType()
; 向数组中添加函数(可以在任何位置完成).
funcArray.Push(One)
funcArray.Push(Two)
; 创建一个使用数组作为方法的对象.
obj := {method: funcArray}
; 调用方法(One 和 Two 都会被调用).
obj.method("2nd")
; 将其作为函数调用.
(obj.method)("1st", "2nd")

One(param1, param2) {
    ListVars
    MsgBox
}
Two(param1, param2) {
    ListVars
    MsgBox
}

绑定函数对象

行为像函数, 但只是将预定义的参数传递给另一个函数.

有两种建立绑定函数对象的方式:

可以调用绑定函数对象, 如下例所示. 当绑定函数对象被调用时, 它调用绑定的函数或方法, 传递绑定的参数和后面跟着的调用者传递的任何参数. 未绑定的参数位置是从调用者的参数列表中指定的位置(从左到右). 例如:

fn := RealFn.Bind(1)  ; 只绑定第一个参数
fn(2)    ; 显示 "1, 2"
fn.Call(3) ; 显示 "1, 3"

fn := RealFn.Bind( , 1)  ; 只绑定第二个参数
fn(2, 0)        ; 显示 "2, 1, 0"
fn.Call(3) ; 显示 "3, 1"
fn(, 4)     ; 错误: 'a' 被省略了

RealFn(a, b, c?) {
    MsgBox a ", " b (IsSet(c) ? ", " c : "")
}

ObjBindMethod 可用于绑定方法, 即使是在无法检索到方法本身的引用时. 例如:

Shell := ComObject("Shell.Application")
RunBox := ObjBindMethod(Shell, "FileRun")
; 显示运行对话框.
RunBox

更多复杂的例子, 请参阅 SetTimer.

其他的属性和方法都是从 Func 继承过来的, 但不反映目标函数或方法的属性(不需要作为一个函数来实现). BoundFunc 作为一个匿名的变量函数, 没有其他形式上的参数, 类似于下面的胖箭头函数:

Func_Bind(fn, bound_args*) {
    return (args*) => (args.InsertAt(1, bound_args*), fn(args*))
}