[a134] Class loading in script init Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

[a134] Class loading in script init

08 May 2021, 02:52

Post #3 shows the actual issue I was having, which is technically not an issue i guess.

Old
Last edited by TheArkive on 08 May 2021, 03:57, edited 3 times in total.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

[a134] Class loading in script init

08 May 2021, 03:13

Apologies.

I goofed on the initial post. It is now fixed.

First and third code blocks are now corrected.

The code in the 1st and 3rd blocks works in a131, but not in a134.

EDIT: Attaching the method directly to the instance works:

Code: Select all

g := Gui()
g.NewMethod := test.NewMethod
g.NewMethod()

class test extends Gui.custom {
    Static __New() {
        ; Gui.Prototype.NewMethod := ObjBindMethod(this, "NewMethod")
    }
    
    Static NewMethod() { ; not using _obj as first param when attaching method to instance
        msgbox "I'm new here."
    }
}
Last edited by TheArkive on 08 May 2021, 04:29, edited 1 time in total.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

[a134] Class loading in script init

08 May 2021, 03:55

Well, it seems to be as simple as switching the order, given how classes are loaded now.

In a134 this works:

Code: Select all

class test extends Gui.Custom {
    Static __New() {
        Gui.Prototype.NewMethod := ObjBindMethod(this, "NewMethod")
    }
    
    Static NewMethod(_obj) { ; not using _obj as first param when attaching method to instance
        msgbox "I'm new here."
    }
}

g := Gui()
g.NewMethod()

In this case, creating a class library, with an example up top, is now either less viable, or not viable, unless the example is moved below the class (which is a small concession I admit).

So, when adding #INCLUDEs, the idea is to make sure your classes from included scripts are loaded first when there are events in Static __New().
lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a134] Class loading in script init  Topic is solved

08 May 2021, 07:25

You need to reference the class for it to be initialized. If you don't do it, it happens automatically when the class definition is reached. Before, classes were given priority over everything else (partly because it seemed to be the simplest way to implement class initialization at the time), so if static __new (or something called by it) needed to refer to a global variable, that variable had to be initialized in static __new. Classes would be used just for automatic execution of code at startup, which is not their purpose.
In this case, creating a class library, with an example up top, is now either less viable, or not viable
If this can even be called a "class library", it is not a typical one. The script never refers to the class; it is used only as a platform for defining a function and executing some code at startup, to put that function into some other class. This isn't how classes are intended to be used, so you must make a small concession.

That is,

Code: Select all

(test) ; Force class initialization.

g := Gui()
g.NewMethod()

class test {
    Static __New() {
        Gui.Prototype.NewMethod := ObjBindMethod(this, "NewMethod")
    }
    
    Static NewMethod(_obj) {
        msgbox "I'm new here."
    }
}
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: [a134] Class loading in script init

08 May 2021, 08:47

lexikos wrote:
08 May 2021, 07:25
If this can even be called a "class library", it is not a typical one.

Hah! Indeed :P

I was only trying to give the simplest example possible to illustrate my learning issue.

But this basic format (though usually with "extends Gui.Custom") is what I have been using lately to extend custom control functionality, with fairly decent success (IronToolbar, Scintilla Complete, and currently unposted Rebar control). Usually I've been reassigning the base of the control type on creation to not interfere with other such customizations. Certainly not all Gui.Custom controls are created equally.

If not calling that a "class library", what should it be called then? (Just so I get my stuff right.)
lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a134] Class loading in script init

09 May 2021, 03:51

What you posted, I would call "a contrived example containing an unreferenced class definition".

If a function library provides one or more functions for the script to call, a class library provides one or more classes for the script to call or otherwise access.

If a library script is intended to have some effect merely by being #included, you could call it an #include library. It really doesn't matter whether the library's initialization is implemented within a class, function or just global code.

In this case the purpose of the library is to extend an existing class with additional properties, so you could call it a class-extension library. In C# it could be done by defining extension methods, where the class containing the method definitions is pretty much superfluous (and need not be referenced directly), as in this case.


Around the time I first added classes, I considered making method definitions like this:

Code: Select all

Gui.NewMethod() {
    msgbox I'm new here.
}
I don't recall whether this was before or after the class definition syntax was added (v1.1.00). Before class definitions, I might have chosen not to do it because (without being predefined) Gui still had to be defined somehow, perhaps like this:

Code: Select all

Gui := Object()
Gui.NewMethod() {
    msgbox I'm new here.
}
...but then Gui.NewMethod has to be evaluated only when execution reaches it, which might be unexpected. I think part of the reason for a class definition was that (like a function) it could be defined after the code that uses it.

After class definitions, I might have chosen not to do it simply because it was redundant. Now there are also property definitions to consider.

Since then, I've learned that Ruby (which I've never used) uses the concept of "open classes". Basically, you would add a method to Gui like this:

Code: Select all

class Gui {
    NewMethod() {
        msgbox "I'm new here"
    }
}
...but you lose detection of errors where the definition of an entirely new class is intended. It also allows class definitions to be split into different locations, which might be good or bad. C# has partial classes, where I think every "part" of the class must be declared partial, so it's less flexible but accidental conflicts would be reported (as to be expected from that type of language).

I considered class extends Gui {} or similar, but the semantics didn't seem right, and ultimately I don't know that it's a good idea to add language features specifically to support the modification of standard classes.

@Helgef brought up an idea,
Helgef wrote:
27 Apr 2020, 02:40
Perhaps future changes could allow something like class Array extends std.Array { }
...but I think Array in particular is (ironically) a good example of not solving the problem. Arrays are created and returned by built-in functions, created for variadic functions, and by the [] syntax, none of which reference the global/standard name Array, let alone the one within the script's current namespace. It would be reasonable for [] and variadic functions to resolve Array within the current namespace, but not so for arrays returned by built-in functions or passed between modules.

I just learned that Ruby has an experimental feature called refinements. Refinements are, it seems, a kind of lexically-scoped extension to an existing class. In other words, module A could add Gui.Prototype.NewMethod in a way that module A can call GuiObj.NewMethod for any instance of Gui, but for the same object, GuiObj.NewMethod doesn't exist (or can have a different definition) within module B. However, I think that involves more complex dynamic lookup of methods. (I suppose it's basically the dynamic equivalent of C#'s extension methods, which would be handled at compile-time.)


However, for custom controls, you don't want to add methods to Gui.Custom; you want to create a new custom control class, as in literally class MyControl extends Gui.Custom, but then use it in any Gui. This doesn't require any new language features, just API features. I intentionally deferred thinking about or working on it because 1) current solutions seem sufficient, 2) I suppose it isn't very common to create custom controls, 3) it can be added in a future release, 4) I figure that prototypes for any potential integration features can generally be created in script (and I leave that to everyone else), 5) I've burned out any interest I had in Gui for quite a while, which makes it difficult to think about, and 6) I don't want the v2.0 project to take decades (oops!).
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: [a134] Class loading in script init

09 May 2021, 04:51

lexikos wrote: What you posted, I would call "a contrived example containing an unreferenced class definition".

Heh, that's fair. I wasn't trying to make the code snippit useful beyond illustrating a point or concept.

Thanks for taking time to share your knowledge. The latter half was a very interesting tangent.

lexikos wrote: I intentionally deferred thinking about or working on it because 1) current solutions seem sufficient, 2) I suppose it isn't very common to create custom controls, 3) it can be added in a future release, 4) I figure that prototypes for any potential integration features can generally be created in script (and I leave that to everyone else), 5) I've burned out any interest I had in Gui for quite a while, which makes it difficult to think about, and 6) I don't want the v2.0 project to take decades (oops!).

I must admit I like the direction the Gui updates are going, so thanks for that :D, and for pushing past burn-out for the benefit of the language and the community.

I have found a lot of joy and functionality in AutoHotkey, and I appreciate how it just gets better and better.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: andy_BSZY, Descolada, songdg and 25 guests