"outer" keyword - get a reference to the outer class (parent, super, root, inner)

Post your working scripts, libraries and tools for AHK v1.1 and older
iseahound
Posts: 1445
Joined: 13 Aug 2016, 21:04
Contact:

"outer" keyword - get a reference to the outer class (parent, super, root, inner)

06 Apr 2018, 02:56

Place the following code in a nested class.

Code: Select all

outer[p:=""] {
   get {
      ; Define the period as a delimiter for v1 & v2 compatibility purposes.
      static period := ".", _period := (A_AhkVersion < 2) ? period : "period"
      ; Finds the name of the outer class by recursively truncating this.__class.
      ; If this function is nested inside "default" then the outer class would be
      ; the name of the class that contains "default". Void if not nested in at least 2 classes.
      if ((__outer := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
         Loop Parse, __outer, %_period%
            outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
      ; Test if this property is nested in one class. If so, return the global class "p".
      ; Otherwise if the subclass p is not found or undefined, return an empty string.
      if IsObject(outer)
         return (p) ? outer[p] : outer
      else
         return (p) ? %p% : ""
   }
}


inner[]
{
   get {
      ; Gets a reference to the current class.
      ; Returns void if this function is not nested in a class.
      if (_class := this.__class)
         Loop, Parse, _class, .
            inner := (A_Index=1) ? %A_LoopField% : inner[A_LoopField]
      return inner
   }
}
Example

Code: Select all

a := new bird.owl()
a.outer.layEgg()

bird.owl.outer.owl.outer.sparrow.outer.owl.outer.sparrow.outer.layEgg()

class bird {

   layEgg(){
      text := "hi :)"
      _text := (A_AhkVersion < 2) ? text : "text"
      MsgBox %_text%
   }

   class owl extends default {
      hoot(){
         return "hoot!"
      }
   }

   class sparrow extends default {
      chirrup(){
         return "chirrup!"
      }
   }
}

class default {
   outer[p:=""] {
      get {
         ; Define the period as a delimiter for v1 & v2 compatibility purposes.
         static period := ".", _period := (A_AhkVersion < 2) ? period : "period"
         ; Finds the name of the outer class by recursively truncating this.__class.
         ; If this function is nested inside "default" then the outer class would be
         ; the name of the class that contains "default". Void if not nested in at least 2 classes.
         if ((__outer := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
            Loop Parse, __outer, %_period%
               outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
         ; Test if this property is nested in one class. If so, return the global class "p".
         ; Otherwise if the subclass p is not found or undefined, return an empty string.
         if IsObject(outer)
            return (p) ? outer[p] : outer
         else
            return (p) ? %p% : ""
      }
   }
}
Old Example
Updated for v2 compatibility.
Last edited by iseahound on 02 Aug 2019, 20:08, edited 8 times in total.
iseahound
Posts: 1445
Joined: 13 Aug 2016, 21:04
Contact:

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 03:11

Does the code look confusing?

this.__class - is a special keyword that returns the full class name. So we need to get the parent class of this class with simple Regular Expression.
RegExReplace(this.__class, "^(.*)\..*$", "$1")) - returns the parent class. However since this is RegExReplace(), if it does not find a match, then the input will be equal to the output.
RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class - If the two sides are not equal we can be reasonably assured that the RegEx has extracted a parent class.
((parent := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class) - Let us save the output of the RegExReplace() into the variable parent.

The last bit of code just separates the parent classes and builds them up.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 08:40

No the code is just incorrect.
super classes are not classes that contain other classes. It refers to parent classes that are extended by a child.
AutoHotkey has .super it's called .base.
Your code is useful - but I would probably rename it.
Recommends AHK Studio
User avatar
rommmcek
Posts: 1475
Joined: 15 Aug 2014, 15:18

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 09:21

Yes, the code is useful, not only by its extended feature, but it instigates to learn the class-es
My attempts:

Code: Select all

bird.owl.super.layEgg() ;\/
MsgBox % a.hoot()  ;\/
MsgBox % a.super.owl.hoot()
MsgBox % a.super.sparrow.chirrup() ;\/
MsgBox % a.chirrup() ; does not work
Question: Why a.hoot() works and a.chirrup() doesn't?

@nnnik or anybody familiar with class-es: Can you give example (or link) for .base, similar to iseahound's code!
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 10:07

rommmcek .chirrup() is part of the sparrow class - however a is an owl it can only hoot.

The .base code probably won't look the same as iseahounds code - after all it will be used for something completely different and it all comes down to what you want to do.
Once again the closest thing to Javas .super is .base - however there are still massive differencies.
I think there are good tutorials with regards to classes out there.
Recommends AHK Studio
User avatar
rommmcek
Posts: 1475
Joined: 15 Aug 2014, 15:18

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 10:25

Thanks nnnik, now it's obvious even to me:

Code: Select all

b:= new bird.sparrow()
MsgBox % b.chirrup()
Works!
Edit: Or still better

Code: Select all

a := new bird()
a.layEgg()  ;\/
bird.owl.super.owl.super.sparrow.super.owl.super.sparrow.super.layEgg() ;\/
bird.owl.super.layEgg() ;\/
MsgBox % bird.owl.hoot() ;\/
MsgBox % a.owl.hoot() ;\/
MsgBox % bird.sparrow.chirrup() ;\/
MsgBox % a.sparrow.chirrup() ;\/
return
#Include, super_keyWord.ahk
Some day I'll try .base too!
iseahound
Posts: 1445
Joined: 13 Aug 2016, 21:04
Contact:

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 16:42

nnnik wrote:Your code is useful - but I would probably rename it.

You're right. I read through the python documentation of super() as well as the java implementation of super() and it is equivalent to AutoHotkey's obj.base. I'll rename this function from super to parent instead. It turns out that you can't access a parent property from a nested class in Java, without directly naming the parent class!
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: "super" keyword - call parent class like in Java

06 Apr 2018, 17:12

Comparing AutoHotkey to the examples in the Java documentation,
Java's super.printMethod(); is equivalent to AutoHotkey's base.printMethod().
Java's super(); within a constructor is equivalent to AutoHotkey's base.__new().

These invoke the superclass versions of the method/constructor. It is not the same as .base, which returns the immediate base (the class of an instance, or a superclass of a class). .base is relative to the preceding object, whereas base. is relative to the class which defined the current method, and the latter can only be used to invoke the class, not to retrieve its reference.

I think that nesting one class inside another does not imply a parent-child relationship, just "inner" and "outer".
iseahound
Posts: 1445
Joined: 13 Aug 2016, 21:04
Contact:

"outer" keyword - get a reference to the outer class (parent, super, root)

06 Apr 2018, 17:59

lexikos wrote:I think that nesting one class inside another does not imply a parent-child relationship, just "inner" and "outer".
I seem to agree that parent-child is a bit of a stretch. super is the correct keyword in mathematics, as in class b is a subset of set a and class a is a superset of class b. Naming things is hard, what does it mean to go "up one on the hierarchy"? I'll finalize on the term "outer" since it is the simplest description of what's happening when I run the code.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

06 Apr 2018, 19:50

I disagree; class a is not a superset of class b. Class a is a set which contains class b. Class b does not contain any of the methods, properties or nested classes of class a, and vice versa. They are two unrelated sets.

However, default's members are a subset (not superset) of bird.owl's members (after flattening the hierarchy): default contains some of the same items as bird.owl. Conversely, bird.owl's members are a superset (not subset) of default's.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

08 Apr 2018, 14:14

Comparing AutoHotkey to the examples in the Java documentation,
Java's super.printMethod(); is equivalent to AutoHotkey's base.printMethod().
Java's super(); within a constructor is equivalent to AutoHotkey's base.__new().
Isn't it more like:
Java's super.printMethod(); is equivalent to AutoHotkey's base.printMethod.call( this ).
Java's super(); within a constructor is equivalent to AutoHotkey's base.__new.call( this ).
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

08 Apr 2018, 15:29

@ nnnik, base.method.call(this) will mean someClassName.method.call(this).call(this) where someClassName.method.call(this) doesn't invoke meta functions.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

09 Apr 2018, 13:02

It does invoke a __Get meta function. ( Only if the method is not defined directly inside itself though )
Also isn't that a .call( this ) too much in your code?
And yes I'm perfectly aware of that. In fact that is closer to the Java behaviour.
If you look closely you will see that the printMethod() method in the Java documentation is not static.
This also means that using Javas .super() operator will invoke the parents instance method on the current instance in the parent scope of the instance.
Essentially it's exactly like I said the closest we have is someClassName.method.call( this )
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

10 Apr 2018, 00:59

nnnik wrote:Also isn't that a .call( this ) too much in your code?
Yes, but it was no typo, I thought you said base.printMethod().call( this ). Please disregard my comments.

Also, thanks for sharing iseahound :wave:.

Cheers.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

10 Apr 2018, 05:01

nnnik wrote:Isn't it more like:
No, it is not.

I don't think I can explain it without just basically repeating what I said in my previous post or the documentation.

base.method (even when not followed by ()) is not the same as className.method (regardless of which class name you use).
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

10 Apr 2018, 06:42

Thats interesting - I did not know that.
Thanks for the info
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

10 Apr 2018, 07:08

Code: Select all

class testClass {
	
	test( string ) {
		Msgbox string . "`n&this( after calling the method with this.base.test() ): " . &this . "`n&testClass: " . &testClass
	}
	
	test2() {
		this.base.test( "&this: " . &this )
	}
	
}

testInstance := new testClass()
testInstance.test2()
This simple test seems to contradict your statment.
The most similar case to Javas OOP in AHk is when the 1st and the 2nd are the same.
Of course Javas Object inheritance is a few times more complex than AutoHotkeys - and during the reduction you could come to different conclusions.
In AutoHotkey .base refers to the class of the object. .base.method() therefore is calling a static method. However .super.method() in this case is calling a method upon the instance not the class - it is nonstatic.
Therefore AutoHotkeys equivalent of .super.method() is .super.method.call( this ) since it acts upon the instance and executes a method defined in the parent class.
Recommends AHK Studio
iseahound
Posts: 1445
Joined: 13 Aug 2016, 21:04
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root)

10 Apr 2018, 22:13

Here's the complement property to "outer": "inner"

Code: Select all

      inner[]
      {
         get {
            ; Gets a reference to the current class.
            ; Returns void if this function is not nested in a class.
            if (_class := this.__class)
               Loop, Parse, _class, .
                  inner := (A_Index=1) ? %A_LoopField% : inner[A_LoopField]
            return inner
         }
      }
It's useful for getting a reference to the current class. If I'm working with an object that I don't want to instantiate (new this) but I still want to store values this.value := 7 but I don't want to hard code the name like testClass.value := 7 then I'll use the inner property. this.inner.value := 7.

One reason to avoid instantiation is to store a static value within the global object that is a class. This way the value is retained until the script is exited or reloaded. As to why I don't hard code the className? Stylistic preference.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: "outer" keyword - get a reference to the outer class (parent, super, root, inner)

11 Apr 2018, 00:35

nnnik, please read my earlier post. Then read the manual. base. and .base. are not the same thing.
I wrote:These invoke the superclass versions of the method/constructor. It is not the same as .base, which returns the immediate base (the class of an instance, or a superclass of a class). .base is relative to the preceding object, whereas base. is relative to the class which defined the current method, and the latter can only be used to invoke the class, not to retrieve its reference.
iseahound wrote:Here's the complement property to "outer": "inner"
You can use this.base for that.

It is not "the current class" in the sense of the class inside which the code lies. It is the class which this is an instance of, and may be a subclass of the class which defined the method/property.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: GollyJer and 132 guests