为什么我的实例变量在 AHK 中表现得像 class 变量?

Why is my instance variable acting like a class variable in AHK?

这是我正在尝试做的事情的基本结构:

OutputDebug % "~~~~~ START ~~~~~"

tempA := new ClassA()
tempB := new ClassB()
tempC := new ClassC()

tempA := 0
tempB := 0
tempC := 0

OutputDebug % "~~~~~ END ~~~~~"

return 

class Base {
    ivar := 0

    __New(inValue) {
        this.ivar := new Debug(inValue)
    }

    __Delete() {
        this.ivar := 0
    }
}


class Debug {
    value := 0

    __New(inValue) {
        this.value := inValue
        OutputDebug % "Create Debug [" this.value "]"
    }

    __Delete() {
        OutputDebug % "Delete Debug [" this.value "]"
    }
}


class ClassA extends Base {
    __New() {
        base.__New("A")
        OutputDebug % "Create ClassA"
    }

    __Delete() {
        base.__Delete()
        OutputDebug % "Delete ClassA"
    }
}


class ClassB extends Base {
    __New() {
        base.__New("B")
        OutputDebug % "Create ClassB"
    }

    __Delete() {
        base.__Delete()
        OutputDebug % "Delete ClassB"
    }
}


class ClassC extends Base {
    __New() {
        base.__New("C")
        OutputDebug % "Create ClassC"
    }

    __Delete() {
        base.__Delete()
        OutputDebug % "Delete ClassC"
    }
}

当这是 运行 时,我在调试日志中得到以下输出:

Create Debug [A]
Create ClassA
Create Debug [B]
Delete Debug [A]
Create ClassB
Create Debug [C]
Delete Debug [B]
Create ClassC
Delete Debug [C]
Delete ClassA
Delete ClassB
Delete ClassC

然而,这不是我所期望的...这是我正在寻找的输出:

Create Debug [A]
Create ClassA
Create Debug [B]
Create ClassB
Create Debug [C]
Create ClassC
Delete Debug [A]
Delete ClassA
Delete Debug [B]
Delete ClassB
Delete Debug [C]
Delete ClassC

我正在使用 Notepad++,我已经安装了 DBGp 插件,它可以工作,我可以单步执行脚本...问题似乎与实例化 class 'Base' 的时间有关作为 Class[ABC] 的基础。当它到达 'ivar := 0' 行时,它实际上是在删除前一个对象......如果它是一个 class 变量,而不是作为一个实例变量,这将是有意义的!

我根本不了解 AHK 如何做 classes? :(

这个问题的解决方法非常简单。

不要用关键字命名您的 classes! AutoHotkey 中的变量不区分大小写,因此 'Base' 与 'base'.

相同

因此,当我使用 'base' 时,它会将其视为 'Base',这就是为什么我观察到 'ivars' 表现得像 class 变量是正确的。 .因为它被不经意地以这种方式使用!

如果您将上述示例代码中的 class 'Base' 重命名为 'BaseX' 一切正常!


在 AHK 论坛上,AHK 的创建者也在那里回复了我的查询:

base only has special meaning if followed by a dot . or brackets [], so
code like obj := base, obj.Method() will not work. Scripts can disable the
special behaviour of base by assigning it a non-empty value; however, this
is not recommended. Since the variable base must be empty, performance may
be reduced if the script omits #NoEnv.

来源:Objects

这部分是为了向后兼容使用 "base" 作为变量名的脚本(在它变成 "keyword" 之前),部分是由于它的实现方式。您可能会注意到 ListVars 显示 base[0 of 0]: - 它由默认基对象实现,条件是目标是名为 base 的空变量。因此,可以这样做:

class Base  {
    M() {
        MsgBox % A_ThisFunc
    }
}
class C extends Base {
    M() {
        local base
        MsgBox % A_ThisFunc
        base.M()
    }
}
C.M()

您可以通过向默认基对象添加 __call 元函数来自己挂钩 base.Method()(其中基不是对象),但在脚本中您无法获取目标变量的名称。