Code: Select all
q := new uber.c
text := q.test1
_text := (A_AhkVersion < 2) ? text : "text"
MsgBox %_text%
q.test2()
q.test3()
; At each base "level" the name of the __class and the number of objects are displayed.
; The ground level should be an empty class with 2 objects. [_extends, test1]
; The -1 (base) level should be the class "c" with 5 objects. [__Class, __extends, __Init, extends, outer]
; The -2 level should be the class "b" with 6 objects. [__Class, __extends, __Init, extends, outer, test2]
; The -3 level should be the class "a" with 4 objects. [__Class, __delete, __New, test3]
; The -4 level is invalid.
; Why does the ground level have an empty class? Because class names are like types - they live in obj.base.
; When a class is instansiated all the old functions go into its base object and its properties (_extends, test1) become the top level.
try level0 := "Ground Level: " ObjRawGet(q, "__class") "`nNumber of Objects: " q.Count()
try level1 := "Level -1: " ObjRawGet(q.base, "__class") "`nNumber of Objects: " q.base.Count()
try level2 := "Level -2: " ObjRawGet(q.base.base, "__class") "`nNumber of Objects: " q.base.base.Count()
try level3 := "Level -3: " ObjRawGet(q.base.base.base, "__class") "`nNumber of Objects: " q.base.base.base.Count()
try level4 := "Level -4: " ObjRawGet(q.base.base.base.base, "__class") "`nNumber of Objects: " q.base.base.base.base.Count()
; v2 compatible code.
_level0 := (A_AhkVersion < 2) ? level0 : "level0"
_level1 := (A_AhkVersion < 2) ? level1 : "level1"
_level2 := (A_AhkVersion < 2) ? level2 : "level2"
_level3 := (A_AhkVersion < 2) ? level3 : "level3"
_level4 := (A_AhkVersion < 2) ? level4 : "level4"
; v2 compatible code.
try MsgBox %_level0%
try MsgBox %_level1%
try MsgBox %_level2%
try MsgBox %_level3%
try MsgBox %_level4%
; Necessary or the object will delete itself immediately.
; When the script exits the __delete method will be called.
Sleep 2500
class uber {
class a {
__New() {
text := A_ThisFunc
_text := (A_AhkVersion < 2) ? text : "text"
MsgBox %_text%
}
__delete() {
text := A_ThisFunc
_text := (A_AhkVersion < 2) ? text : "text"
MsgBox %_text%
}
test3() {
text := "This is a method of class a."
_text := (A_AhkVersion < 2) ? text : "text"
MsgBox %_text%
}
}
class b {
static extends := "a"
_extends := this.__extends()
__extends(subbundle := "") {
object := this.outer[this.extends]
bundle := ((object.haskey("__extends")) ? object.__extends(true) : object)
(subbundle) ? (this.base := bundle) : (this.base.base := bundle)
return (subbundle) ? this : ""
}
outer[p:=""] {
get {
static period := ".", _period := (A_AhkVersion < 2) ? period : "period"
if ((__outer := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
Loop Parse, __outer, %_period%
outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
return IsObject(outer) ? ((p) ? outer[p] : outer) : ((p) ? %p% : "")
}
}
test2() {
text := "This is a method of class b."
_text := (A_AhkVersion < 2) ? text : "text"
MsgBox %_text%
}
}
class c {
static extends := "b"
_extends := this.__extends()
__extends(subbundle := "") {
object := this.outer[this.extends]
bundle := ((object.haskey("__extends")) ? object.__extends(true) : object)
(subbundle) ? (this.base := bundle) : (this.base.base := bundle)
return (subbundle) ? this : ""
}
outer[p:=""] {
get {
static period := ".", _period := (A_AhkVersion < 2) ? period : "period"
if ((__outer := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
Loop Parse, __outer, %_period%
outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
return IsObject(outer) ? ((p) ? outer[p] : outer) : ((p) ? %p% : "")
}
}
test1 := "This is a property of class c."
}
}
Original Post
Motivation: To create classes that can be nested or not nested.
Example #1 - Two classes are nested inside a bigger class, "uber"
Code: Select all
q := new uber.a()
MsgBox % q.red
q.test()
class uber {
class a {
red := "red"
base := this.base
base.base := (this.outer.b) ? this.outer.b : b
outer[] {
get {
if ((_class := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
Loop, Parse, _class, .
outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
return outer
}
}
}
class b {
test() {
MsgBox % "This is the new extended class!"
}
}
}
Code: Select all
q := new a()
MsgBox % q.red
q.test()
class a {
red := "red"
base := this.base
base.base := (this.outer.b) ? this.outer.b : b
outer[] {
get {
if ((_class := RegExReplace(this.__class, "^(.*)\..*$", "$1")) != this.__class)
Loop, Parse, _class, .
outer := (A_Index=1) ? %A_LoopField% : outer[A_LoopField]
return outer
}
}
}
class b {
test() {
MsgBox % "This is the new extended class!"
}
}