Help understanding the interpreter, OOP calling methods in class Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
swyfty
Posts: 5
Joined: 06 Feb 2023, 14:50

Help understanding the interpreter, OOP calling methods in class

Post by swyfty » 06 Feb 2023, 22:28

I banged my head against this for a good portion of the day, I have it working now but do not understand why and am looking for some better understanding of why what I thought should work didn't and why the other methods work. Looking at the code below where I am assigning events to the buttons. I could not for the life of me understand why the third didn't work at all.

script error kept on telling me: Gui.Button has no property buttonTS. I'm a try it till it works level at programming. my last CS class was over 20 years ago, and I rarely ever program. So if someone could explain why the second assignment with the Bind works, but the third doesn't, I 'd appreciate it.

Code: Select all

Class TargetingInterface extends Gui {
    __New() {
        super.__New("+Resize",, this)
        this.buttonToT := super.Add("Button", "x0 y0 w36 h12", "ToT")
        this.buttonTM := super.Add("Button", "x0 y12 w36 h12", "TM")
        this.buttonTS := super.Add("Button", "x0 y24 w36 h12", "TS")
        this.buttonToT.OnEvent("Click", "ToTselect")  ; works!
        this.buttonTM.OnEvent("Click", this.TMselect.Bind(this))  ;also works!
        this.buttonTS.OnEvent("Click", this.TSselect())  ; doesn't work,  and this was what I thought should work...
        this.preamble := ""
        this.ToTselect()
        this.Show

    }
    ;Target of Main Target
    ToTselect(*) {
        this.buttonTM.Enabled := 1
        this.buttonTS.Enabled := 1
        this.buttonTOT.Enabled := 0    
        this.preamble := "F2, k"
    }
    ;TargetMain
    TMselect(*) {
        this.buttonToT.Enabled := 1
        this.buttonTS.Enabled := 1
        this.buttonTM.Enabled := 0
        this.preamble := "F2"
    }
    ;Target Self
    TSselect(*) {
        this.buttonTOT.Enabled := 1
        this.buttonTM.Enabled := 1
        this.buttonTS.Enabled := 0
      
        this.preamble := "F1"  
    }
    getPreamble() {
        return this.preamble
    }
}

t_win := TargetingInterface()

neogna2
Posts: 590
Joined: 15 Sep 2016, 15:44

Re: Help understanding the interpreter, OOP calling methods in class  Topic is solved

Post by neogna2 » 07 Feb 2023, 08:42

This is out of my league but I'll give it a shot answering anyway and let others point out if I'm mistaken...

OnEvent's Callback parameter has type "String or Function Object". But you've put this.TSselect() there, which is an expression that returns neither of those because your TSselect() method returns nothing. In contrast your this.TMselect.Bind(this) does return a BoundFunc object to be called when an event is raised.

swyfty
Posts: 5
Joined: 06 Feb 2023, 14:50

Re: Help understanding the interpreter, OOP calling methods in class

Post by swyfty » 07 Feb 2023, 08:51

neogna2 wrote:
07 Feb 2023, 08:42
This is out of my league but I'll give it a shot answering anyway and let others point out if I'm mistaken...

OnEvent's Callback parameter has type "String or Function Object". But you've put this.TSselect() there, which is an expression that returns neither of those because your TSselect() method returns nothing. In contrast your this.TMselect.Bind(this) does return a BoundFunc object to be called when an event is raised.
Thank you! this now makes a little more sense, I guess its because I did not fully understand the difference between a method and a function and incorrectly conflating the two.

neogna2
Posts: 590
Joined: 15 Sep 2016, 15:44

Re: Help understanding the interpreter, OOP calling methods in class

Post by neogna2 » 07 Feb 2023, 15:21

swyfty wrote:
07 Feb 2023, 08:51
the difference between a method and a function
I don't think that's the issue here.
I think the issue is that you thought this.TSselect() sets TSselect as callback function. But what really happens is that on button press AutoHotkey first tries to determine what the callback function for OnEvent will be, encounters the expression this.TSselect(), proceeds to evaluate that expression, that is calls the TSselect method, and tries to use the method's return as the OnEvent callback function. But TSselect has no return set so AutoHotkey defaults to return an empty string and since there exists no method with an empty string for a name an error is thrown. At least that's what happens in this kind of situation when using OnEvent outside classes and I think the same thing happens here.

It may help to think of OnEvent lines as involving two steps.
Step 1 determines what the callback function will be.
Step 2 is when the callback function gets called.
This small script makes the two steps easier to spot because step 1 is here performed during auto-execution.

Code: Select all

G := Gui()
G.Add("Button", , "click me").OnEvent("Click", B() )
G.Show()

B() {
    MsgBox("step 1: auto-execute called B and will use its return, function object A, as OnEvent callback function")
    return A
}

A(*) {
    MsgBox("step 2: button clicked, callback function A called")
}
If you comment out the line return A the script will throw the kind of error I'm talking about.

edit: clarified text

Post Reply

Return to “Ask for Help (v2)”