"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
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, inner)

11 Apr 2018, 03:12

I see - this is the first time I have seen base.method() being used. I just always misunderstood this part of the documentation.
Recommends AHK Studio
iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

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

11 Apr 2018, 20:30

lexikos wrote:You can use this.base for that.

Actually using this.base gives me undesirable behavior...

Code: Select all

class a {
    save(){
        this.base.var := 7
    }
}

a.save()
MsgBox % a.var ; blank

class b extends Empty {
    save(){
        this.base.var := 7
    }
}

class Empty {
    ; Nothing to see here.
}

b.save()
MsgBox % b.var ; 7


; Expected, but undesirable behavior. 
MsgBox % empty.var
where if I have class a, and I want to hide a variable under its super global scope, it doesn't work unless a base class exists and extends creates that base class. Also for obvious reasons, I would not like to modify class Empty.
iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

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

20 Nov 2018, 21:40

Small update to the first post to address cases where the "outer" property is nested in one class. The user can now call this.outer["subclass"] to retrieve the global class named "subclass". This is useful when the class may or may not be nested inside another class.

Code: Select all

outer[p:=""] {
   get {
      ; Determine if there is a parent class. this.__class will retrive the
      ; current instance's class name. Split the class string at each period, 
      ; using array notation [] to dereference. Void if not nested in at least 2 classes.
      if ((_class := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
         Loop, Parse, _class, .
            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 no subclass (p) is specified, return an empty string.
      if IsObject(outer)
         return (p) ? outer[p] : outer
      else
         return (p) ? %p% : ""
   }
}
iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

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

02 Aug 2019, 20:03

Condensed Version (Highly Recommended)

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% : ""
   }
}
Updated to be v2 compatible.
User avatar
GollyJer
Posts: 69
Joined: 19 Sep 2015, 19:33
Contact:

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

04 Apr 2024, 00:35

Hi @iseahound. I've been trying to get this to work with V2 without success.
I get "Error: This variable has not been assigned a value." on the line If IsObject(outer)

PS - I added code to fix a "can't compare numbers to strings" issue I was having with the version check.

Code: Select all

#Requires AutoHotkey v2.0

outer[p := ""] {
      get {
         ; Define the period as a delimiter for v1 & v2 compatibility purposes.
         static period := "."
         version := StrSplit(A_AhkVersion, ".")
         majorVersion := version[1]
         _period := (majorVersion < 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% : ""
      }
 }
iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

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

04 Apr 2024, 12:41

Something like this:

Code: Select all

#Requires AutoHotkey v2.0

a := bird.owl()
a.outer.layEgg()
msgbox bird.owl.outer.owl.prototype.hoot()
bird.owl.outer.owl.outer.sparrow.outer.owl.outer.sparrow.outer.layEgg()

class bird {

   static layEgg() {
      MsgBox "hi :)"
   }

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

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

class default {
   outer {
      get {
         if ((__outer := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
            Loop Parse, __outer, "."
               outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
         return outer
      }
   }
   static outer {
      get {
         if ((__outer := RegExReplace(this.prototype.__class, "^(.*)\..*$", "$1")) != this.__class) {
            Loop Parse, __outer, "."
               outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
            return outer
         }
      }
   }
}
You should probably read up on prototypes and static methods inside classes. Instances of classes are now separate from static classes. (By instances I mean being able to create multiple instansiations of the class. By a static class I mean a singleton, a class where everything inside has the word static prefixed to it. This is a global class of which there is only one copy that can be shared.)
User avatar
GollyJer
Posts: 69
Joined: 19 Sep 2015, 19:33
Contact:

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

04 Apr 2024, 15:24

Read up on the new structure of Classes. I get it now. Thanks!

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 70 guests