Autoit3's maps and function pointers make it possible to put an OO style layer on it, in much the same way that you can with JS and Perl.
But the lack of a
new keyword, and any kind of
this mechanism, and namespaces, means more programmer discipline is required.
A class Doubler with a static method Doubler, and an object method DoubleMe:
https://pastebin.com/aETcFCYw
; Doubler.au3
#include-once
; class Doubler {
func Doubler(byref $this, $n) ; constructor(n) {
; properties
$this["n"] = $n ; this.n = n;
; methods
$this["Double"] = DoublerDouble ; this.Double = DoublerDouble;
$this["DoubleMe"] = DoublerDoubleMe ; this.DoubleMe = DoublerDoubleMe;
endfunc ;
func DoublerDouble(byref $this, $x) ; Double(x) {
return $x*2 ; return x*2;
endfunc ; }
func DoublerDoubleMe(byref $this) ; DoubleMe() {
$this["n"] = $this["Double"]($this, $this["n"]) ; this.n = this.double(this.n);
endfunc ; }
; }
In use:
; main.au3 ; let obj;
#include "Doubler.au3"
local $obj[]
$obj["constructor"] = Doubler ;
$obj["constructor"]($obj, 128) ; obj = new Doubler(128);
MsgBox(0, "", $obj["Double"]($obj, 32)) ; alert(obj.Double(32));
;
$obj["DoubleMe"]($obj) ; obj.DoubleMe();
MsgBox(0, "", $obj["n"]) ; alert(obj.n);
You don't have to use an include file btw, but it's the best way to manage code in larger projects.
As I say, discipline is required:
- You have to prefix, with the class name, the base names of the functions that are assigned to be methods, because they're in the single namespace that Au3 has.
- You have to supply the object's map variable as first parameter to all its methods. (Strictly speaking you needn't do that with the constructor, and static methods, but I find it easier to be consistent and always supply the map variable.)
- The aforesaid parameter must be byref if you want the method to modify any properties. Again, it's easier to be consistent and use byref for all methods.
But if you have to use Au3 to implement something, this is a way to avoid spaghetti code and function/variable name collisions.
Map elements can be set to other maps, or arrays. So your object can 'has-a' another object. But take note that Au3 cannot do more than one layer of dereference:
; Not allowed!
; $obj["anotherObj"] = []
; $obj["anotherObj"]["constructor"] = OtherClass
; $obj["anotherObj"]["constructor"]( $obj["anotherObj"] )
;
; instead do it stepwise:
local $temp[]
$temp["constructor"] = OtherClass
$temp["constructor"]($temp)
$obj["anotherObj"] = $temp
It would be possible to write a 'Ootoit' preprocessor that translated a more sugary syntax into Au3 code that used these protocols. Rather in the style of the old RATFOR tool that put a C-style layer on top of Fortran.