[v2] __Static property and the :: operator

Propose new features and changes
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

[v2] __Static property and the :: operator

10 Feb 2023, 13:14

With the separation of static properties and methods into a separate object from the prototype, the ability to access those static properties and methods from within instances of the class has reduced flexibility and is less DRY.

Consider v1:

Code: Select all

class Application
{
    class Helper
    {
        SOME_PROPERTY1 := 1
        SOME_PROPERTY2 := 2
        
        InstanceMethod()
        {
            return this.SOME_PROPERTY1 + this.SOME_PROPERTY2
        }
    }
}
As opposed to v2:

Code: Select all

class Application {
    class Helper {
        static SOME_PROPERTY1 := 1
        static SOME_PROPERTY2 := 2
        
        InstanceMethod() {
            return Application.Helper.SOME_PROPERTY1 + Application.Helper.SOME_PROPERTY2
        }
    }
}
With the v2 version, I now have to write each class name in three places rather than one (decreasing DRYness), and the implementation of InstanceMethod becomes more difficult to read with references to outer class(es) that should not be of any concern to Helper.

A common pattern I used in v1 was to nest libraries. For this example, that would be to have Application as one file Application.ahk, and Helper as a different file Helper.ahk, then to write Application.ahk as

Code: Select all

class Application {
    ...
    ...
    ...
    #IncludeAgain %A_LineFile%\..\Helper.ahk
}
This pattern both simulates a "traits" feature (such as in PHP) as well as gives a robust option for, when building a library, bundling dependent libraries without screwing up the global scope of whoever is using my library*. For example, this strategy is used by Chrome.ahk to include a custom JSON library optimized for Chrome's API quirks without conflicting with any other json library that someone using Chrome.ahk might want to import into the global scope under the name JSON.
*Future module support may offer an alternate path to address this problem

However, combining this strategy with AHKv2 makes using statics very difficult as the library to be nested (my JSON library) would need to code in the name(s) of any parent classes, which just isn't possible to know ahead of time.

To combat this, I've considered adding this property definition to my libraries (maybe not applied to the base Class, but to each of my libraries individually):

Code: Select all

Class.Prototype.base.DefineProp("__Static", {get: classStaticGet})
classStaticGet(this) {
	for name in StrSplit(this.__Class,".")
		obj := IsSet(obj) ? obj.%name% : %name%
	return obj
}
This allows me to re-write my original v2 example:

Code: Select all

class Application {
    class Helper {
        static SOME_PROPERTY1 := 1
        static SOME_PROPERTY2 := 2
        
        InstanceMethod() {
            return this.__Static.SOME_PROPERTY1 + this.__Static.SOME_PROPERTY2
        }
    }
}
Observing the new code, I no longer have to specify the potentially-unknown parent class name from the nested class (fixing one of my grievances) and I no longer have to repeat the class's name in every place that a static property is accessed (fixing another), but with the tradeoff of the increased overhead and extra code elsewhere.



With that context in mind, what I would like to see is a __Static property be added natively to the Class object, to eliminate the tradeoffs.

Furthermore, a new operator of :: which automatically accesses the __Static property, similar to how . accesses __Get, would be a fantastic addition to reduce clutter, allowing people to write this::SOME_PROPERTY rather than this.__Static.SOME_PROPERTY.
User avatar
kczx3
Posts: 1643
Joined: 06 Oct 2015, 21:39

Re: [v2] __Static property and the :: operator

10 Feb 2023, 15:01

I had no idea that v1 code could do that...
iseahound
Posts: 1448
Joined: 13 Aug 2016, 21:04
Contact:

Re: [v2] __Static property and the :: operator

10 Feb 2023, 22:43

If your class is extended, your __Static will resolve to the derived class instead of it remaining contravariant (invariant) to the original class. This would produce behavior where subclasses have their own internal static variables, where you might've meant it to beshared by all members, even subclass members of the class.
iseahound
Posts: 1448
Joined: 13 Aug 2016, 21:04
Contact:

Re: [v2] __Static property and the :: operator

10 Feb 2023, 23:02

So essentially, I see two scenarios:

The first is that your class carries static variables meant to be public or editable in some sense.

Code: Select all

class MyClass {
   static setting1 := 1
   static setting2 := 2
}
Since you expect your user to be able to edit the global settings, having the class be nestable via #include is moot. Because the user could set their own settings via MyClass.setting1 := 42.

The second is that your class carries private variables that are meant to be private and also be:
  1. nestable in another class
  2. extendable by another subclass
  3. includable such as a mixin

Code: Select all

#Requires AutoHotkey v2.0

class mixin {
   static private(n?) {
      static var := 3
      if IsSet(n)
         var := n
      return var
   }
}

class MyClass {
   __New() {
      this.private := mixin.private
   }
}

a := MyClass()
b := MyClass()
MsgBox a.private()
b.private(42)
MsgBox a.private()
Note that this approach is stronger because in addition to remaining invariant under nested classes, extended classes, it also remains invariant as an included function within a class.
Slightly condensed function
just me
Posts: 9467
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [v2] __Static property and the :: operator

11 Feb 2023, 05:30

v1:

Code: Select all

class Application
{
    class Helper
    {
        SOME_PROPERTY1 := 1
        SOME_PROPERTY2 := 2
        
        InstanceMethod()
        {
            return SOME_PROPERTY1 + SOME_PROPERTY2
        }
    }
}
does not work for me.
iseahound
Posts: 1448
Joined: 13 Aug 2016, 21:04
Contact:

Re: [v2] __Static property and the :: operator

11 Feb 2023, 08:27

Couldn't get it to work either. Something similar in Java is possible however...

Code: Select all

// Java code
public class MyClass {
    
    // Doesn't work if static is removed here, as the class isn't instantiated. 
    static int a = 1;
    static int b = 2;
    
    public static void main(String args[]) {
      System.out.printf("Sum of a + b = %d", a + b);
    }
}
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [v2] __Static property and the :: operator

11 Feb 2023, 14:10

just me wrote:
11 Feb 2023, 05:30
does not work for me.
Apologies, there should have been this. qualifiers to the property accesses. I'll adjusted the original post to have these
iseahound wrote: If your class is extended, your __Static will resolve to the derived class instead of it remaining contravariant (invariant) to the original class. This would produce behavior where subclasses have their own internal static variables, where you might've meant it to beshared by all members, even subclass members of the class.
I apologize as I may be misunderstanding, but this seems irrelevant to the subject at hand. I would expect __Static to resolve to the derived class, not the base class. I'm not trying to do anything like what you're suggesting here. I'm not trying to make private properties, I'm not trying to make properties that are shared between derived classes, I just want a way to reference static functions and properties from an instantiated class without writing the class name everywhere.

Maybe another illustrative example could help?

Code: Select all

#Include <JSON> ; where JSON is a different JSON library that does different things that the user picked based on their needs

class GeeksBigBrowserAutomationLibrary {
    class JSON { ; where JSON is my own JSON library with explicit support for certain features, and follows my own API definitions 
        static MAGIC_FLAG := 4
        static Parse(str) {
            obj := Map()
            ; Here, assuming I develop JSON as an independent project, it is impossible to actually put GeeksBigBrowserAutomationLibrary.JSON.MAGIC_FLAG
            DllCall("something", "Str", str, "Ptr", obj, "UInt", this::MAGIC_FLAG, "Int") ; parse the Str by external code
            return obj
        }
    }
    
    static UriDecode(a) {
        ; do some decoding
    	return a
    }
    
    DoThing() {
        ; instead of this
        ;return GeeksBigBrowserAutomationLibrary.UriDecode(GeeksBigBrowserAutomationLibrary.JSON.Parse("...").value)
        ; I want to be able to do this
        return this::UriDecode(this::JSON.Parse("...").value)
    }
}

instance := GeeksBigBrowserAutomationLibrary()

MsgBox instance.doThing()
iseahound
Posts: 1448
Joined: 13 Aug 2016, 21:04
Contact:

Re: [v2] __Static property and the :: operator

11 Feb 2023, 18:32

You're asking for namespaces, and you're using the existing class structure for this. Lexikos is working on modules / namespaces.

But why do you need static MAGIC_FLAG := 4? You should really return an enumeration of flags, that's what Java would do.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [v2] __Static property and the :: operator

12 Feb 2023, 07:58

I've been using this :arrow: [v2 - a108][Tips] How to create a Class property for instances of a class.. Which I guess would still work, although the text is a bit outdated, most likely. I think something like a class, or as suggested, a __static, property should be built-in. I guess it is either planned or lexikos has a better solution.

Regarding the operator, although I'm not opposed it per se, I do not think it is needed.

Cheers.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [v2] __Static property and the :: operator

13 Feb 2023, 08:09

iseahound wrote:
11 Feb 2023, 18:32
You're asking for namespaces, and you're using the existing class structure for this. Lexikos is working on modules / namespaces.
Please stop saying I'm asking for other things!! I'm not asking for namespaces. I know Lexikos has module and namespace type features on the roadmap. Yes they would be better suited to achieve some of the goals that my example codes display. But I'm not asking for namespaces I'm asking for a simple way to access static properties and methods from an instance of a class like is available in other languages such as PHP and PowerShell (
Spoiler
).

Just because some of my examples will be able to be designed better using functionality that will become available some time in the future does not negate that this simple functionality will have immediate usefulness right now, lasting usefulness in many situations, and is a common feature regularly used in other commodity scripting languages.

iseahound wrote:
11 Feb 2023, 18:32
But why do you need static MAGIC_FLAG := 4? You should really return an enumeration of flags, that's what Java would do.
It's an example, not to mention that AutoHotkey doesn't have enums... The name MAGIC_FLAG was picked to be so generic that the reader could gloss over the specifics of what the property was, assuming that it would be useful to reference it.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [v2] __Static property and the :: operator

13 Feb 2023, 08:59

Helgef wrote:
12 Feb 2023, 07:58
I've been using this :arrow: [v2 - a108][Tips] How to create a Class property for instances of a class.. Which I guess would still work, although the text is a bit outdated, most likely. I think something like a class, or as suggested, a __static, property should be built-in. I guess it is either planned or lexikos has a better solution.

Regarding the operator, although I'm not opposed it per se, I do not think it is needed.

Cheers.
That is a much more effective approach than mine, kudos. I still agree that this should be available as a built-in property under some name, whatever that specific name may end up being.

I don't think the operator is anything crazy to do--as I shared in my last message on this thread, it exists for this purpose in some other scripting languages already. I don't see it conflicting badly with anything already in AHK (`this` is not a valid keyname, and if you used it on an object that did share a name with a key you could wrap the call in parentheses to avoid putting it on the start of a line), and if it were to be implemented it would make the specific name for the underlying property even less important.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [v2] __Static property and the :: operator

04 Mar 2023, 04:29

I don't think the operator is anything crazy
it is not crazy :)

What would be the syntax for just accessing the class itself?
This would probably not work,

Code: Select all

; wanted: the same result as the_class := Application
the_class := this:: 
this could work,

Code: Select all

the_class := (this::)
Cheers.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [v2] __Static property and the :: operator

04 Mar 2023, 11:38

this.__Static if it were to be implemented as I imagined :)
User avatar
cyruz
Posts: 346
Joined: 30 Sep 2013, 13:31

Re: [v2] __Static property and the :: operator

05 Mar 2023, 06:45

Hi geek,

what about %this.__Class%?
ABCza on the old forum.
My GitHub.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [v2] __Static property and the :: operator

05 Mar 2023, 08:57

cyruz wrote:
05 Mar 2023, 06:45
Hi geek,

what about %this.__Class%?
This does not work for nested classes, e.g. A.B
lexikos
Posts: 9593
Joined: 30 Sep 2013, 04:07
Contact:

Re: [v2] __Static property and the :: operator

28 Mar 2023, 01:53

With Object.ahk I almost gave each prototype a class property referring to the had a Object.Prototype.Class property, like this:

Code: Select all

class base {
	static __new() {
		this.prototype.class := this
	}
}

class a extends base {
	__new() {
		this.class.ly()
	}
	static ly() {
		MsgBox A_ThisFunc
	}
}

class b extends base {
	__new() {
		this.class.ly()
	}
	static ly() {
		MsgBox A_ThisFunc
	}
}

a()
b()
The circular reference isn't a problem because the existence of methods prevents the classes from being deleted anyway.

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 8 guests