object classes: redefine __Set() temporarily / general queries

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
derz00
Posts: 497
Joined: 02 Feb 2016, 17:54
Location: Middle of the round cube
Contact:

Re: object classes: redefine __Set() temporarily / general queries

29 Jan 2018, 10:44

Well, in Python there is only (but I'm not experienced enough to be able to say without exception) one way to do any one thing. You can't use dot notation for dicts (equivalent of assoc arrays) to index keys. You can only get keys with dict[key]. And everything in general, other than dictionaries and lists is more consistent in behaviour and strict in syntax. This area is AHK's greatest weakness, and one of Python's great strengths. But AHK can do some things (automation of Windows OS, hotkeys) easier (for the user) than Python.
try it and see
...
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

01 Feb 2018, 21:42

- @derz00: And is it easy to do nested arrays, because some of that sounds like one-dimensional dictionaries e.g. the Scripting.Dictionary object.

- @Ask For Help/@Ask For Helgef: Relevant to this:
objects: backport AHK v2 Gui/Menu classes to AHK v1 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=43530
I'm trying to interact with a class object directly. Properties/methods seemed fine, but not __Set. Is there an obvious reason for this? Thanks.

Code: Select all

q:: ;class object v. an instance
;we don't see __Set() when we try to assign to the class object
MyPropertyAndSetClass.MyProperty := 1
MsgBox, % MyPropertyAndSetClass.MyProperty
MyPropertyAndSetClass.MyProperty2 := 2
MyPropertyAndSetClass.MyMethod()

MsgBox

obj := new MyPropertyAndSetClass
obj.MyProperty := 1
MsgBox, % obj.MyProperty
obj.MyProperty2 := 2
obj.MyMethod()
return

class MyPropertyAndSetClass
{
	static storeMyProperty := 2
	__Set(vKey, vValue)
	{
		MsgBox, % A_ThisFunc
		if (vKey = "MyProperty2")
		{
			MsgBox, % "MyProperty2"
			return
		}
	}
	MyMethod()
	{
		MsgBox, % A_ThisFunc
	}
	MyProperty[]
	{
		get
		{
			MsgBox, % A_ThisFunc
			return this.storeMyProperty
		}
		set
		{
			MsgBox, % A_ThisFunc
			return this.storeMyProperty := value
		}
	}
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 02:29

Code: Select all

class Proxy {
	__New() {
		init := new Proxy()
		if init
			return init
		Proxy := this
	}
	__Call( fn, p* ){
		return Target[fn]( p* )
	}
	__Set( p* ) {
		value := p.pop()
		return Target[p*] := value
	}
	__Get( p* ){
		return Target[p*]
	}
}
class Target {
	__New() {
		init := new Target()
		if init
			return init
		Target := this
	}
	test() {
		Msgbox Hello World!
	}
}
I think this would make a nice code puzzle:
Try to remove the .base of the Proxy object.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 03:32

Both of the __new methods will cause infinite recursion, maybe you meant static init := new ....
You are welcome to submit the puzzle in the code puzzle thread. Please state the rules and objectives :wave:
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 07:20

Re. class objects. Do class objects have a base object? And is there a base object for standard AutoHotkey arrays that be accessed somehow?

Code: Select all

q:: ;do object classes have a base object?
obj := new MyOneMethodClass

vOutput := ""
for vKey, vValue in obj
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

vOutput := ""
for vKey, vValue in obj.base
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

obj.base := {"__Get":"InStr"}
vOutput := ""
for vKey, vValue in obj.base
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

vOutput := ""
for vKey, vValue in MyOneMethodClass
;for vKey, vValue in MyOneMethodClass.base
;for vKey, vValue in MyOneMethodClass.__Class.base
;for vKey, vValue in MyOneMethodClass.__Class
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput
return

class MyOneMethodClass
{
	__Get()
	{
	}
	MyMethod()
	{
	}
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 10:27

when one class objects extends another the extended class is the .base object of the extending class:

Code: Select all

t := new A()
Msgbox % t.base.base.__Class
class A extends B {
}
class B extends A {
}
Sadly I don't think that there is a documented .base class for arrays and general objects
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 12:32

- @nnnik: Thanks for the example. It's helped me a lot with figuring out the example below.
- This test suggests that all class objects have a base object.
- This test also suggests that a class object, that does not extend another class object, has a standard base object, just like standard AutoHotkey arrays.

Code: Select all

obj := new C()
Msgbox % obj.base.__Class ;C
Msgbox % obj.base.base.__Class ;B
Msgbox % obj.base.base.base.__Class ;A

Msgbox % A.base.__Class ;(blank)
Msgbox % B.base.__Class ;A
Msgbox % C.base.__Class ;B

class A
{
}
class B extends A
{
}
class C extends B
{
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 16:12

- Is it possible to make the __Set meta-function for a class object be its own __Set meta-function?
- I was able to do this by using a line outside of the class definition, but is it possible to do this within the class definition? Thanks.

Code: Select all

;make a class object use its own meta-function
;MySetClass.base := {"__Set":"MyFunc"} ;works
MySetClass.base := {"__Set":"MySetClass.__Set"} ;works
MySetClass.1 := 1

class MySetClass
{
	;base := {"__Set":"MyFunc"}
	;static base := {"__Set":"MyFunc"}
	;__Init()
	;__New()
	;{
	;	ObjRawSet(this, "base", {"__Set":"MyFunc"})
	;	ObjRawSet(MySetClass, "base", {"__Set":"MyFunc"})
	;	this.base := {"__Set":"MyFunc"}
	;}
	__Set(p*)
	{
		MsgBox, % A_ThisFunc
	}
}

MyFunc()
{
	MsgBox, % A_ThisFunc
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 20:20

That would mean you want to use a Singleton.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

02 Feb 2018, 21:30

- This is great nnnik. Cheers.
- I looked at this post:
OOP design patterns in AHK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 44#p175344
- I now know what the distinction is between the two examples:
Name: Singleton
Name: automatically initialized singleton
- In both cases there is only one object per class, but the automatically-initialised singleton is made ready on startup, the other requires the use of the 'new' keyword.
- The issue relating to __Set() in the 'backport' example mentioned earlier on this page, now has a solution. It seemed easy to define and use the class object directly for certain methods/properties, but more difficult to do this directly for certain meta-functions (this is resolved below).
- I had to go all around the world to find 8 lines of code.
- Any suggestions on the script below are welcome.

Code: Select all

MyStaticSingletonClass.key1 := 1
MyStaticSingletonClass.key2 := 2

vOutput := ""
for vKey, vValue in MyStaticSingletonClass.base
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

class MyStaticSingletonClass
{
	__New()
	{
		;'static' makes AHK run this on script startup
		static init := new MyStaticSingletonClass
		if init
			return init
		MyStaticSingletonClass.base := {__Set:"MyStaticSingletonClass.__Set"}
	}
	__Set()
	{
		MsgBox, % A_ThisFunc
	}
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

03 Feb 2018, 04:45

No I think you are making it more difficult on yourself.
I actually meant using the 3rd type:
"Super global automatically initialized Singleton"

Code: Select all

class MyStaticSingletonClass
{
	__New()
	{
		;'static' makes AHK run this on script startup
		static init := new MyStaticSingletonClass
		if init
			return init
		MyStaticSingletonClass := This
	}
	__Set()
	{
		MsgBox, % A_ThisFunc
	}
}
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

03 Feb 2018, 06:34

- Great, I see this line there as well on the page:
Name: super global automatically initialized Singleton
- So it appears you only changed one line of my script, but it does make it much simpler, especially if multiple meta-functions are involved.

Code: Select all

;this works because MyStaticSingletonClass is super-global
;before:
;MyStaticSingletonClass.base := {__Set:"MyStaticSingletonClass.__Set"}
;after:
MyStaticSingletonClass := this
- Is there a particular reason you use new MyClass(), instead of new MyClass? Or MyProperty[], instead of MyProperty? I mention it because it's a key style decision, that can't easily be reversed at a later date. Thanks.
- Btw aren't all 3 of the singleton examples, super-global? I.e. aren't all class objects super-global? Although I appreciate it's hard to give each example a good descriptive/100% precise name.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

03 Feb 2018, 07:21

I find it easier to use empty brackets when no brackets are needed because that is consistent with how things look when they are needed.
The other singletons were meant to be gotten with `New Singleton()` instead of accessing their super global variable directly - what you did was essentially abusing them :P
BTW if you don't use a dynamic assignment to overwrite the singletons class variable

Code: Select all

#Warn, ClassOverwrite
[/c] will throw an error.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

03 Feb 2018, 20:52

- @nnnik: Thanks very much for the info re. dynamic variables, I've made a note to test any examples for my tutorial in AHK v2 (more things explicitly fail rather than silently fail), and with #Warn.
- Thanks for the info re. () and [].

- Interesting to know that this has been discussed.
Override the default *object* base class - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=5828
There is no default object base class. You cannot override that which does not exist.

You can override {} and []: Customizing Object() and Array()
- It links here:
[AHK_L] Customizing Object() and Array() - Tutorials - AutoHotkey Community
http://www.autohotkey.com/board/topic/8 ... and-array/
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: object classes: redefine __Set() temporarily / general queries

04 Feb 2018, 02:54

Sadly I expected that much when it came to a general base defined by [] and {}. Also it's rather pointless to overwrite Object unless you find a way to recreate

Code: Select all

Object(Obj|Ptr)
[/c]
(Overwriting is one reason why I prefer specific functions/methods for specific tasks rather than all round general purpose functions/methods. And this also won't help with classes.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

04 Feb 2018, 08:34

- @nnnik: That's an interesting argument, make functions less general, and more specialised, so that overwriting one causes less problems.

- One general question re. objects. Is it possible to redefine the base object, other than by doing obj.base := obj2.

- Another general question. AFAIK assignments in the class body, or using 'this.', create content that can be retrieved, whereas other assignments, within methods, are local to the method (unless they are global), just like in any normal function, and thus cannot be retrieved via the object.

Code: Select all

;a relevant link:
;object classes: redefine __Set() temporarily / general queries - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=42674&p=193941#p193941

q:: ;are d/e and g/h inaccessible? (just like any variable inside a function)
MsgBox, % MyAssignmentClass.a ;(blank)
MsgBox, % MyAssignmentClass.b ;B
MsgBox, % MyAssignmentClass.c ;(blank)
MsgBox, % MyAssignmentClass.d ;(blank)
MsgBox, % MyAssignmentClass.e ;(blank)
MsgBox, % MyAssignmentClass.f ;(blank)
MsgBox, % MyAssignmentClass.g ;(blank)
MsgBox, % MyAssignmentClass.h ;(blank)
MsgBox, % MyAssignmentClass.i ;(blank)

MsgBox

obj := {}
MyAssignmentClass.__Init.Call(obj)
msgbox % obj.a ;A

oArray := new MyAssignmentClass
MsgBox, % oArray.a ;A
MsgBox, % oArray.b ;B
MsgBox, % oArray.c ;(blank)
MsgBox, % oArray.d ;(blank)
MsgBox, % oArray.e ;(blank)
MsgBox, % oArray.f ;F
MsgBox, % oArray.g ;(blank)
MsgBox, % oArray.h ;(blank)
MsgBox, % oArray.i ;(blank)

oArray.MyMethod()
MsgBox, % oArray.i ;I

class MyAssignmentClass
{
	a := "A"
	static b := "B"
	;this.c := "C" ;doesn't work
	__New()
	{
		d := "D"
		static e := "E"
		this.f := "F"
	}
	MyMethod()
	{
		g := "G"
		static h := "H"
		this.i := "I"
	}
}
- Btw I couldn't find any reference on the forum to __Init.Call(obj). Or even Call(obj) in this context.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: object classes: redefine __Set() temporarily / general queries

04 Feb 2018, 13:36

- One general question re. objects. Is it possible to redefine the base object, other than by doing obj.base := obj2.
You cannot reassign it in any other way, as far as I know, but you can redefine it just like any other object. Eg, if obj.base == obj1, then obj1.f := func("f") enables you to do obj.f(...), and so on...

Code: Select all

;this.c := "C" ;doesn't work
It works provided that this was previously declared in the class body, see instance variables.
- Another general question. [...]

Code: Select all

; ...
All that relates to the basics of instance and class variables, and methods (and functions ). I'm not sure if you are asking, or just stating something?

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: object classes: redefine __Set() temporarily / general queries

04 Feb 2018, 14:53

- By 'Another general question', I was stating what I believed to be fact, but giving people the chance to contradict this.
- It's a little surprising as a beginner, that assignments, within the class body, have a special meaning, whereas assignments within meta-functions/methods/properties, if local, are inaccessible just like variables within any normal function.
- __Init.Call(obj)? Anyone?
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: object classes: redefine __Set() temporarily / general queries

04 Feb 2018, 14:58

- -
- I find it surprising if it is surprising. :D
- what are you asking?

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada, Google [Bot], ntepa and 128 guests