When do you use static class properties?

Get help with using AutoHotkey and its commands and hotkeys
A_User
Posts: 36
Joined: 21 Aug 2017, 01:15

When do you use static class properties?

22 Nov 2017, 15:07

Hi,

I'm trying to understand how static class properties work in AutoHotkey and see if I can use them in my scripts.

I expected the first line in the message box in the following code shows the changed value. But it doesn't.

Code: Select all

_o1 := new StaticProperties
_o1.sStaticVar := "changed"
_o1.sVar := "changed"

_o2 := new StaticProperties

msgbox % "1: " _o2.sStaticVar "`n"  ; <-- this does not show `changed`
    . "2: " _o2.sVar
    
class StaticProperties {
    static sStaticVar := "this is static"
    sVar := "tihs is NOT static"    
}
It seems it's possible to directly modify the value by not insntantiating the class like `StaticProperties.sStaticVar := "something else"`.

But I'm surprized that changing the value of properties having the same name declared as static from an instantiated object does not actually modify their static values. So they seem to be entirely different entities although they share the same name.

Also modifying them from an extended class isn't possible using the `this` and `base` keywords.

Code: Select all

_o2 := new StaticProperties2    ; should update the static property in the consturctor.
_o1 := new StaticProperties

msgbox % _o1.sStaticVar  ; <-- this does not show `updated`
    
class StaticProperties {
    static sStaticVar := "this is static"
}

class StaticProperties2 extends StaticProperties {
    __New() {
        this.base.sStaticVar := "updated"   ; doesn't update the base static value
        base.sStaticVar := "updated"        ; doesn't update the base static value
        this.sStaticVar := "updated"        ; doesn't update the base static value
        ; StaticProperties.sStaticVar := "updated"    ; this does
        
        ; msgbox % this.base.sStaticVar   ; shows `updated`
        ; msgbox % base.sStaticVar        ; shows `this is static`        
    }    
}
I find this quite confusing. Especially the part, `msgbox % base.sStaticVar` (commented out) in spite of the assignment done above with `base.sStaticVar := "updated"`.

So when do you use static properties? I thought I could use them for caching values shared among derived objects but at the moment, I find it very difficult to manage.
A_AhkUser
Posts: 1076
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: When do you use static class properties?

22 Nov 2017, 21:11

Hi A_User,

To assign to a class variable, you should always specify the class object itself:
To assign to a class variable, always specify the class object; for example, ClassName.ClassVar := Value
source: Static/Class variables

Also not that all static variables are initialized before the script begins executing (and before the auto-execute section itself). Here's an example with SendInput illustrating this: SendMode, Input is not into effect when the Send command is invoked from the static call of StaticProperties.Init:

Code: Select all

SendMode, Input

_o1 := new StaticProperties
; _o1.sStaticVar := "changed"
StaticProperties.sStaticVar := "changed"
_o1.sVar := "changed"
_o2 := new StaticProperties
msgbox % "1: " . _o2.sStaticVar . "`n" . "2: " . _o1.sVar
StaticProperties.Init() ; does send as reliably and speedly as SendInput does: SendMode, Input came into effect
    
class StaticProperties {
    static sStaticVar := "this is static"
	Init() {
	static __ := StaticProperties.Init() ;  each static variable is initialized only once (before the script begins executing).
	run, notepad
	WinWait, ahk_class Notepad
	WinActivate
	WinWaitActive
	send, % """To assign to a class variable, always specify the class object; for example, ClassName.ClassVar := Value""" ; doesn't send as speedly as SendInput: SendInput as not yet come into effect
	}
    sVar := "tihs is NOT static"
}

Code: Select all

_o2 := new StaticProperties2, _o1 := new StaticProperties
msgbox % StaticProperties2.sStaticVar
    
class StaticProperties {
    static sStaticVar := "this is static"
}
class StaticProperties2 extends StaticProperties {
    __New() {
        this.base.sStaticVar := "updated"
        ; StaticProperties.sStaticVar := "updated"    ; this does
        ; StaticProperties2.sStaticVar := "updated"    ; this does too
    }    
}
A_User
Posts: 36
Joined: 21 Aug 2017, 01:15

Re: When do you use static class properties?

22 Nov 2017, 22:12

Hi,

So when do you use static class variables? I still don't see how I can use them with the current implementation. In other words, in what cases are they useful?
A_AhkUser
Posts: 1076
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: When do you use static class properties?

22 Nov 2017, 23:12

I think it is question of semantics. Let's say you have a Square class: in this case, your slide property is rather intended to be a static property: since each square has 4 slides, one should use Square.slide. Besides, one can note that in this case the property is not intended to change; each square has and will always have 4 slides - and while their color property if any will be in most of implementations rather a instance variable: all square have 4 slides and this one, in particular, is red:

Code: Select all

html =
(
<!DOCTYPE html>
<html>
    <head>
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta charset="utf-8" />
	<title>HTMLFile</title>
    </head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
)

Gui, Add, ActiveX, w400 h400 vDoc, about:<!DOCTYPE html><meta http-equiv="X-UA-Compatible" content="IE=edge">
Doc.document.Open()
Doc.document.Write(html)
Doc.document.Close()
Gui, Show
canvas := Doc.document.getElementById("canvas")

canvas := Doc.document.getElementById("canvas")
ctx := canvas.getContext("2d")
ctx.fillRect(10, 10, 100, 100)
sq := new Square()
return

!i::sq.setColor("red")

Class Square {

	static sides := 4
	color := "green"
	
	setColor(__color) {
	global canvas
	ctx := canvas.getContext("2d")
	ctx.fillStyle := (this.color:=__color)
	ctx.fillRect(10, 10, 100, 100)
	}

}
If, on the contrary, the property is intended to be modificated, the pertinence of using static variables - and always specifying the class object when assigning to such a variable - lies in the fact that such a modification get to the heart of each instance itself. As an example, in games like Final Fantasy X the enemy you face with during the game are always the same: we can see that (and in fact I'm pretty sure it is internally) like the creation of a new instance of a Coeurl, a new instance of a Fungus enemy etc.. Yet, their respective level (and for all new enemy you will face of) evolve along with the level of your character:

Code: Select all

Class Character {
levelUp() {
Enemy.level++
}
}
Class Enemy {
static level := 10
hp := 100
onDamage() {
this.hp--
}
}
A_User
Posts: 36
Joined: 21 Aug 2017, 01:15

Re: When do you use static class properties?

23 Nov 2017, 06:04

I see.

I find it not easy to use where you have to use the literal class name to modify the static property value because sometimes one changes class names and with the current implementation he/she has to rename all the occurrences in the code. This can lead to producing bugs if he/she misses one of them while doing it, especially for a library class written by somebody else using static properties.

I found a workaround not using a literal class name to update a static value but it's a bit clumsy and does not look clean.

Code: Select all

_o2 := new StaticProperties2
msgbox % _o2.sStaticVar ; shows `changed`

class StaticProperties {
    static sStaticVar := "this is static"
}
class StaticProperties2 extends StaticProperties {
    __New() {
        _sClassName := base.__Class
        %_sClassName%.sStaticVar := "changed"
    }    
}
Anyway, thanks for your examples. It helped.

Return to “Ask For Help”

Who is online

Users browsing this forum: flyingDman, LanzasPT, malcev, markc63, TAC109 and 95 guests