- Offizieller Beitrag
Hi,
nachdem ich mich in Lua etwas mehr mit Objekten beschäftigt habe, ist mir erst mal aufgefallen, dass es zur Objektarbeit gar keiner Objekte bedarf.
Lua bildet alle Objekte als Arrays ab.
Was in Lua geht, müßte man doch auch in AutoIt schaffen. Ein Wermutstropfen ist natürlich die Notation. Nur mit den reinen AutoIt-Funktionen kann ich auf meine Methoden und Eigenschaften nicht objektüblich mit Objekt.property zugreifen.
Das hier vorgestellte ist wirklich nur ein Basis-Modell zur Objekt-Orientierten-Programmierung. Aber für einen Tag Arbeit ist es doch schon recht gelungen.
Ich stelle zum Einen das Entwicklungsskript ein, da könnt ihr jeden Schritt nachvollziehen.
Zum Anderen hänge ich die (inzwischen noch etwas überarbeiteten) Funktionen aus dem Entwicklungsskript als UDF + Bsp-Skript an.
Das Skript ist bis jetzt eigentlich mehr eine Spielerei und kann keinesfalls gegen AutoItObject anstinken (das habe ich auch gar nicht vor).
Ich wollte mich etwas mehr mit Objekten beschäftigen und habe eine Möglichkeit gesucht diese halbwegs komfortabel über Arrays abzubilden. Wobei mir die Vererbung wichtig war - und das funktioniert.
Vielleicht findet auch jemand Gefallen daran und möchte es weiterentwickeln, Möglichkeiten gibt es da noch einige.
Also dann Viel Spaß damit.
BAO-Entwicklung
#Region - TimeStamp
; 2012-04-22 01:32:17
#EndRegion - TimeStamp
#Include <Array.au3>
[/autoit] [autoit][/autoit] [autoit];====================================================================================================
; BAO = Basic-AutoIt-Object ( oder BugFix-AutoIt-Object ;=) )
;====================================================================================================
; FUNKTIONEN
; _BAO_Class_Create Erstellt eine Objekt-Klasse
; _BAO_Class_MethodSet Registriert eine Methode für die Klasse
; _BAO_Class_PropSet Registriert oder ändert eine Property der Klasse
; _BAO_Class_ObjCreate Erstellt ein Klassen-Objekt
; _BAO_Class_ObjMethodSet Registriert eine Methode für ein Klassen-Objekt
; _BAO_Class_ObjPropSet Registriert oder ändert eine Property eines Klassen-Objektes
; _BAO_Class_ObjGet Abfragen von Informationen der Klasse und/oder des Klassen-Objektes
; _BAO_Class_ObjMethodCall Aufrufen von Methoden
;====================================================================================================
;====================================================================================================
; KLASSEN
;====================================================================================================
; Funktion zum Erstellen einer Klasse
Func _BAO_Class_Create($_sClass, $_sIndexClass='self')
Local Static $aClass_MethodsTmp, $aClass_PropsTmp, $sClassTmp
Local $aClass[4] ; == Array zum Speichern der Mitglieder dieser Klasse (KlassenObjekte), [Klassenname, Array-Methoden, Array-Properties, Array-KlassenObjekte]
If $_sIndexClass = 'self' Then
Local $aClass_Methods[1] = [0] ; == Array zur Aufnahme der Methoden, Erstellen mit Anzahl der akt. Methoden als erstem Element
Local $aClass_Props[1][2] = [[0]] ; == 2D-Array zur Aufnahme der Properties, Erstellen mit Anzahl der akt. Properties als erstem Element, [['property','value']]
Local $aMembers[1] = [0]
If IsArray($aClass_MethodsTmp) Then $aClass_Methods = $aClass_MethodsTmp
If IsArray($aClass_PropsTmp) Then $aClass_Props = $aClass_PropsTmp
If $sClassTmp <> '' Then $_sClass = $sClassTmp
$aClass[0] = $_sClass
$aClass[1] = $aClass_Methods
$aClass[2] = $aClass_Props
$aClass[3] = $aMembers
$aClass_MethodsTmp = ''
$aClass_PropsTmp = ''
$sClassTmp = ''
Return $aClass
Else
$sClassTmp = $_sClass ; == zu verwendender KlassenObjekt-Name
Local $aTmp = Execute('$' & $_sIndexClass) ; == alle zu vererbenden Informationen aus der "Index-Klasse" abfragen (Methoden und Eigenschaften)
$aClass_MethodsTmp = $aTmp[1]
$aClass_PropsTmp = $aTmp[2]
Return _BAO_Class_Create($_sClass)
EndIf
EndFunc
; == die Klasse "Programmierer" erstellen als Array mit Elementen für Klassennamen, Array Methoden, Array Properties, Array Member
Global $Programmierer = _BAO_Class_Create('Programmierer') ; == WICHTIG! Variablenname == '$' & 'Klassenname'
;====================================================================================================
; METHODEN
;====================================================================================================
; == Methoden für diese Klasse erstellen
;**************************************************************************************************************
; == HINWEIS: Als erster Parameter sind zwingend alle Methoden mit "$_self" zu versehen.
; == In der Funktion zum Aufruf der Methode wird an diesen Paramter das aufrufende Objekt übergeben.
; == Somit kann in den Methoden auf die Properties des KlassenObjektes zugegriffen werden.
; == ZUSÄTZLICHE Parameter werden von der aufrufenden Funktion IMMER als Array übergeben!!
;**************************************************************************************************************
; == unser Programmierer benötigt natürlich Methoden, er sollte zwei Dinge können: Kaffee trinken und Programmieren
Func DrinkCoffee($_self)
ConsoleWrite('-> ' & _BAO_Class_ObjGet($_self, 'name') & ' schlürft Kaffee:' & @CRLF) ; Name des KlassenObjektes aus dem übergebenen Objekt abfragen
ConsoleWrite('>> Hm… lecker Kaffe!' & @CRLF)
EndFunc
Func DoSomething($_self)
Local Static $iDone = 0
$iDone += 1
ConsoleWrite('-> ' & _BAO_Class_ObjGet($_self, 'name') & ' tut etwas:' & @CRLF)
If $iDone = 2 Then
$iDone = 0
ConsoleWrite(">> Man kann's auch übertreiben, erst mal Pause machen!" & @CRLF)
_BAO_Class_ObjMethodCall($_self, 'DrinkCoffee')
Else
ConsoleWrite('>> *programmier*' & @CRLF)
EndIf
EndFunc
; == noch sind die Methoden "herrenlos", wir müssen sie jetzt mit der Klasse "Programmierer" verknüpfen
; == dazu bauen wir uns eine Funktion, die die Methoden setzt:
Func _BAO_Class_MethodSet(ByRef $_aClass, $_sMethod) ; == Parameter: Klassen-Array, Methode als String
Local $aMethods = $_aClass[1] ; == das Methoden-Array zum Bearbeiten aus dem Klassen-Array auslesen
$aMethods[0] += 1 ; == Anzahl Methoden um 1 erhöhen
ReDim $aMethods[$aMethods[0]+1] ; == Array vergrößern
$aMethods[$aMethods[0]] = $_sMethod ; == Methode eintragen
$_aClass[1] = $aMethods ; == bearbeitetes Methoden-Array zurückschreiben in Klassen-Array
EndFunc
; == nun weisen wir mit dieser Funktion die erstellten Methoden der Klasse "Programmierer" zu
_BAO_Class_MethodSet($Programmierer, 'DrinkCoffee')
_BAO_Class_MethodSet($Programmierer, 'DoSomething')
;====================================================================================================
; PROPERTIES
;====================================================================================================
; == Objekte haben neben den Methoden auch Eigenschaften (Properties)
; == Der Unterschied sollte klar sein: Methoden sind ausführbare Funktionen, Properties sind Werte die gelesen/geschrieben werden können
; == Nun wollen wir für unsere Klasse "Programmierer" allgemeingültige Eigenschaften setzen, wahlweise gleich mit Wertzuweisung
Func _BAO_Class_PropSet(ByRef $_aClass, $_sProp, $_vProp='') ; == Parameter: Klassen-Array, Eigenschaft als String, [optional] Wert der Eigenschaft
Local $aProps = $_aClass[2] ; == das Properties-Array zum Bearbeiten aus dem Klassen-Array auslesen
If $aProps[0][0] > 0 Then ; == suchen ob Property vorhanden ==> dann aktualisieren
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sProp Then
$aProps[$i][1] = $_vProp
$_aClass[2] = $aProps
Return
EndIf
Next
EndIf
$aProps[0][0] += 1 ; == Anzahl Properties um 1 erhöhen
ReDim $aProps[$aProps[0][0]+1][2] ; == Array vergrößern
$aProps[$aProps[0][0]][0] = $_sProp ; == Eigenschaft eintragen
$aProps[$aProps[0][0]][1] = $_vProp ; == Wert eintragen
$_aClass[2] = $aProps ; == bearbeitetes Properties-Array zurückschreiben in Klassen-Array
EndFunc
; == Als Eigenschaften der Klasse Programmierer legen wir jetzt fest:
_BAO_Class_PropSet($Programmierer, 'Arbeitsintensität', 'hoch')
_BAO_Class_PropSet($Programmierer, 'Kaffee-Konsum', 'extrem')
;====================================================================================================
; KLASSENOBJEKT
;====================================================================================================
; == jetzt erstellen wir ein Klassenobjekt, also einen Programmierer, der die Eigenschaften der Klasse "Programmierer" besitzt
Func _BAO_Class_ObjCreate(ByRef $_aClass, $_sName) ; == Parameter: Klassen-Array, Name des Klassen-Objektes als String
Local $aClassObj_Methods[1] = [0] ; == Array zur Aufnahme der Methoden erstellen mit Anzahl der akt. Methoden als erstem Element
Local $aClassObj_Props[1][2] = [[0]] ; == 2D-Array zur Aufnahme der Properties erstellen mit Anzahl der akt. Properties als erstem Element, [['property','value']]
Local $objClass[4] = [$_sName, $_aClass[0], $aClassObj_Methods, $aClassObj_Props] ; == [Objektname, Klassenname, Array Objekt-Methoden, Array Objekt-Properties]
Local $aMembers = $_aClass[3] ; == neues KlassenObjekt unter Members in der Klasse registrieren
$aMembers[0] += 1
ReDim $aMembers[$aMembers[0]+1]
$aMembers[$aMembers[0]] = $_sName
$_aClass[3] = $aMembers
Return $objClass
EndFunc
Global $Klaus = _BAO_Class_ObjCreate($Programmierer, 'Klaus')
Global $Peter = _BAO_Class_ObjCreate($Programmierer, 'Peter')
; == Klaus und Peter sind jetzt "Objekte" mit den
; == Lokalen Eigenschaften: "name" und "class" und den
; == Globalen Methoden der Klasse: "DrinkCoffee" und "DoSomething"
;====================================================================================================
[/autoit] [autoit][/autoit] [autoit]; Wir wollen natürlich jetzt auch für das einzelne Klassenobjekt individuelle Methoden und Properties setzen können
Func _BAO_Class_ObjMethodSet(ByRef $_objClass, $_sMethod) ; == Parameter: Klassen-Objekt, Methode als String
Local $aMethods = $_objClass[2] ; == das Methoden-Array zum Bearbeiten aus dem KlassenObjekt-Array auslesen
$aMethods[0] += 1 ; == Anzahl Methoden um 1 erhöhen
ReDim $aMethods[$aMethods[0]+1] ; == Array vergrößern
$aMethods[$aMethods[0]] = $_sMethod ; == Methode eintragen
$_objClass[2] = $aMethods ; == bearbeitetes Methoden-Array zurückschreiben in KlassenObjekt-Array
EndFunc
Func _BAO_Class_ObjPropSet(ByRef $_objClass, $_sProp, $_vProp='') ; == Parameter: KlassenObjekt, Eigenschaft als String, [optional] Wert der Eigenschaft
Local $aProps = $_objClass[3] ; == das Properties-Array zum Bearbeiten aus dem KlassenObjekt-Array auslesen
If $aProps[0][0] > 0 Then ; == suchen ob Property vorhanden ==> dann aktualisieren
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sProp Then
$aProps[$i][1] = $_vProp
$_objClass[3] = $aProps
Return
EndIf
Next
EndIf
$aProps[0][0] += 1 ; == Anzahl Properties um 1 erhöhen
ReDim $aProps[$aProps[0][0]+1][2] ; == Array vergrößern
$aProps[$aProps[0][0]][0] = $_sProp ; == Eigenschaft eintragen
$aProps[$aProps[0][0]][1] = $_vProp ; == Wert eintragen
$_objClass[3] = $aProps ; == bearbeitetes Properties-Array zurückschreiben in KlassenObjekt-Array
EndFunc
; == Wir erstellen nun eine Methode, die nur einer unserer Programmierer als Lokale Methode zugewiesen bekommt
Func JustABreake($_self)
ConsoleWrite('-> Anordnung von: ' & _BAO_Class_ObjGet($_self, 'name') & @CRLF)
ConsoleWrite('!> Jetzt ist PAUSE!' & @CRLF)
EndFunc
; == Diese Methode darf nur Klaus ausführen
_BAO_Class_ObjMethodSet($Klaus, 'JustABreake')
; == Und nun weisen wir den beiden noch ein paar individuelle Eigenschaften zu
_BAO_Class_ObjPropSet($Klaus, 'Position', 'Chef')
_BAO_Class_ObjPropSet($Klaus, 'Gehalt', 4500)
_BAO_Class_ObjPropSet($Peter, 'Hobby', 'Nerd')
_BAO_Class_ObjPropSet($Peter, 'Freundin', 'keine')
;====================================================================================================
[/autoit] [autoit][/autoit] [autoit]; == Wäre natürlich schick, wenn man diese Informationen abfragen kann, also brauchen wir eine Funktion dafür
; == Wobei wir jetzt aufpassen müssen, da es sowohl Lokale (nur für das einzeln Klassenobjekt gültige) als auch Globale (für alle Objekte der Klasse gültige) Eigenschaften und Methoden geben kann.
; == Priorität haben also Lokale Einträge, sollte dort nichts gefunden werden, wird auf Globale Einträge geprüft.
; == Parameter $_sWhat:
; == "about" gibt alle vorhandenen Informationen zum KlassenObjekt aus als 2D-Array: [[name], [class], [Lokale_Meth,..,..], [Globale_Meth,..,..], [Lokale_Props,..,..], [Globale_Props,..,..]]
; == "count" gibt die Anzahl der Mitglieder der Klasse zurück
; == "members" gibt ein Array mit den Mitgliedern der Klasse zurück
; == "name" gibt den Name des Klassenobjektes zurück
; == "class" gibt den Name der Klasse zurück
; == "methods_l" gibt ein Array aller Lokalen Methoden zurück
; == "methods_g" gibt ein Array aller Globalen Methoden zurück
; == "props_l" gibt ein 2D-Array aller Lokalen Properties zurück
; == "props_g" gibt ein 2D-Array aller Globalen Properties zurück
; == alles_andere Abfrage bezieht sich auf eine einzelne Property
Func _BAO_Class_ObjGet($_objClass, $_sWhat, $_sAlternative=-1) ; == Parameter: Klassen-Objekt, Abfragebegriff als String, "$_sAlternative": bei Abfrage einer Propertie - wenn nicht gefunden wird dieser Alternativwert zurückgegeben (Standard: -1)
Local $aClass = Execute('$' & Execute('$_objClass[1]')); == Zugriff auf das Klassenarray über den im Klassenobjekt hinterlegten Klassennamen [name, Array-Meth, Arr-Props, Array-Member]
Local $vRet, $aProps, $fFound = False, $aAbout[6][2], $aTmp
Switch $_sWhat ; == was wird abgefragt
Case 'about' ; == Alle Informationen zum KlassenObjekt abfragen
$aAbout[0][0] = $_objClass[0] ; == Objekt-Name
$aAbout[1][0] = $_objClass[1] ; == Klassen-Name
$aTmp = $_objClass[2] ; == Lokale Methoden
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[2][$i-1] = $aTmp[$i]
Next
EndIf
$aTmp = $aClass[1] ; == Globale Methoden
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[3][$i-1] = $aTmp[$i]
Next
EndIf
$aTmp = $_objClass[3] ; == Lokale Properties
If $aTmp[0][0] > 0 Then
If UBound($aAbout,2) < $aTmp[0][0] Then ReDim $aAbout[6][$aTmp[0][0]]
For $i = 1 To $aTmp[0][0]
$aAbout[4][$i-1] = $aTmp[$i][0]
Next
EndIf
$aTmp = $aClass[2] ; == Globale Properties
If $aTmp[0][0] > 0 Then
If UBound($aAbout,2) < $aTmp[0][0] Then ReDim $aAbout[6][$aTmp[0][0]]
For $i = 1 To $aTmp[0][0]
$aAbout[5][$i-1] = $aTmp[$i][0]
Next
EndIf
$vRet = $aAbout
Case 'count' ; == Anzahl der Mitglieder der Klasse ausgeben
$aTmp = $aClass[3]
$vRet = $aTmp[0]
Case 'members' ; == Mitglieder der Klasse ausgeben (Array)
$aTmp = $aClass[3]
$vRet = $aTmp
Case 'name' ; == Name des KlassenObjektes ausgeben
$vRet = $_objClass[0]
Case 'class' ; == Name der Klasse ausgeben
$vRet = $_objClass[1]
Case 'methods_g' ; == das Methoden-Array aus dem Klassen-Array auslesen
$vRet = $aClass[1]
Case 'props_g' ; == das Properties-Array aus dem Klassen-Array auslesen
$vRet = $aClass[2]
Case 'methods_l' ; == das Methoden-Array aus dem KlassenObjekt-Array auslesen
$vRet = $_objClass[2]
Case 'props_l' ; == das Properties-Array aus dem KlassenObjekt-Array auslesen
$vRet = $_objClass[3]
Case Else ; == alles andere ist eine Abfrage zu einer einzelnen Eigenschaft
$aProps = $_objClass[3] ; == Priorität beachten, zuerst lokal abfragen
If $aProps[0][0] > 0 Then
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sWhat Then
$vRet = $aProps[$i][1]
$fFound = True
ExitLoop
EndIf
Next
EndIf
If Not $fFound Then
$aProps = $aClass[2] ; == danach global abfragen
If $aProps[0][0] > 0 Then
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sWhat Then
$vRet = $aProps[$i][1]
$fFound = True
ExitLoop
EndIf
Next
EndIf
If Not $fFound Then $vRet = $_sAlternative ; == abgefragte Property gibt es nicht
EndIf
EndSwitch
Return $vRet
EndFunc
; == Dann lassen wir uns doch mal die Anzahl der Mitglieder der Klasse von Klaus (also "Programmierer") ausgeben
; == Wobei wir hier direkt das KlassenObjekt (also Klaus oder Peter) zur Abfrage verwenden
ConsoleWrite('Anzahl Mitglieder der Klasse "' & _BAO_Class_ObjGet($Klaus, 'class') & '": ' & _BAO_Class_ObjGet($Klaus, 'count') & @CRLF)
; == das stimmt
; == und nun wollen wir alle Mitglieder der Klasse auslesen, laut Definition erhalten wir ein Array
$aMembers = _BAO_Class_ObjGet($Klaus, 'members')
If $aMembers[0] > 0 Then
ConsoleWrite('Mitglieder der Klasse "' & _BAO_Class_ObjGet($Klaus, 'class') & '": ' & @CRLF)
For $i = 1 To $aMembers[0]
ConsoleWrite(@TAB & $aMembers[$i] & @CRLF)
Next
EndIf
; == Nun schauen wir uns mal zuerst die Übersicht zu Klaus und Peter an
$aAbout = _BAO_Class_ObjGet($Klaus, 'about')
_ArrayDisplay($aAbout)
$aAbout = _BAO_Class_ObjGet($Peter, 'about')
_ArrayDisplay($aAbout)
; == Jetzt prüfen wir mal, ob die Zuordnung der lokalen und globalen Properties stimmt.
; == 'Kaffee-Konsum' ist Global und muss bei beiden vorhanden sein:
ConsoleWrite('Kaffee-Konsum von ' & _BAO_Class_ObjGet($Klaus, 'name') & ': ' & _BAO_Class_ObjGet($Klaus, 'Kaffee-Konsum') & @CRLF)
ConsoleWrite('Kaffee-Konsum von ' & _BAO_Class_ObjGet($Peter, 'name') & ': ' & _BAO_Class_ObjGet($Peter, 'Kaffee-Konsum') & @CRLF)
; == OK, das passt schon mal
; == Nun fragen wir mal das Gehalt ab, dürfte ja nur bei Klaus vorhanden sein. Bei Peter muß der Standardwert (-1) zurückgegeben werden
ConsoleWrite('Gehalt von ' & _BAO_Class_ObjGet($Klaus, 'name') & ': ' & _BAO_Class_ObjGet($Klaus, 'Gehalt') & @CRLF)
ConsoleWrite('Gehalt von ' & _BAO_Class_ObjGet($Peter, 'name') & ': ' & _BAO_Class_ObjGet($Peter, 'Gehalt') & @CRLF)
; == Und auch das tut, was es soll.
; == noch für Hobby, das nur bei Peter sein darf
ConsoleWrite('Hobby von ' & _BAO_Class_ObjGet($Klaus, 'name') & ': ' & _BAO_Class_ObjGet($Klaus, 'Hobby') & @CRLF)
ConsoleWrite('Hobby von ' & _BAO_Class_ObjGet($Peter, 'name') & ': ' & _BAO_Class_ObjGet($Peter, 'Hobby') & @CRLF)
; == Auch, wie gewünscht.
; == Jetzt wollen wir mal eine Property ändern
_BAO_Class_ObjPropSet($Peter, 'Hobby', 'Schachspiel')
ConsoleWrite('Hobby von ' & _BAO_Class_ObjGet($Peter, 'name') & ': ' & _BAO_Class_ObjGet($Peter, 'Hobby') & @CRLF)
; == auch das ist OK
; == Nun noch mal alle Lokalen Properties mit Werten von Klaus und Peter jeweils auf einen Blick
$aProps = _BAO_Class_ObjGet($Klaus, 'props_l')
_ArrayDisplay($aProps)
$aProps = _BAO_Class_ObjGet($Peter, 'props_l')
_ArrayDisplay($aProps)
;====================================================================================================
; Methoden aufrufen
; == Nun müssen wir nur noch die Methoden aufrufen und auch hierbei die Gültigkeit Lokaler und Globaler Methoden prüfen
; == Wenn die Methode mehrere Parameter erfordert, diese als Array übergeben; ein Einzelparameter braucht nicht in ein Array gepackt werden
; == als erster Parameter wird IMMER das Klassenobjekt selbst mit übergeben, somit kann in der Methode auf Properties dieses Objekts zugegriffen werden
Func _BAO_Class_ObjMethodCall($_objClass, $_sMethod, $_vParam='')
Local $aParam[1], $fFound = False
If Not IsArray($_vParam) Then
$aParam[0] = $_vParam
Else
$aParam = $_vParam
EndIf
Local $aMethods = $_objClass[2] ; == zuerst bei den Lokalen Methoden nachschauen
If $aMethods[0] > 0 Then
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
ExitLoop
EndIf
Next
EndIf
If Not $fFound Then ; == dann bei den Globalen
Local $aClass = Execute('$' & Execute('$_objClass[1]'))
$aMethods = $aClass[1]
If $aMethods[0] > 0 Then
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
ExitLoop
EndIf
Next
EndIf
EndIf
If Not $fFound Then Return -1 ; == Aufruf enthält keine gültige Methode
If $_vParam = '' Then
Return Call($_sMethod, $_objClass) ; == evtl. Rückgabewert der Funktion wird ausgegeben
Else
Return Call($_sMethod, $_objClass, $aParam) ; == evtl. Rückgabewert der Funktion wird ausgegeben
EndIf
EndFunc
; == Also jetzt das Wichtigste im Programmierer-Alltag: Kaffee Trinken
ConsoleWrite(@CRLF & 'Klaus soll Kaffee trinken:' & @CRLF)
_BAO_Class_ObjMethodCall($Klaus, 'DrinkCoffee')
; == Na, das klappt doch prima
; == Und nun Arbeiten, am Besten wir sagen es ihm 2-mal.
ConsoleWrite(@CRLF & 'Klaus soll Arbeiten:' & @CRLF)
_BAO_Class_ObjMethodCall($Klaus, 'DoSomething')
_BAO_Class_ObjMethodCall($Klaus, 'DoSomething')
; == Tja, so reagieren die Jungs.
; == Wir hatten ja eine Lokale Methode für Klaus erstellt, das wollen wir nun testen
ConsoleWrite(@CRLF & 'Klaus darf Pause ansagen:' & @CRLF)
_BAO_Class_ObjMethodCall($Klaus, 'JustABreake')
; == Das funktioniert, wie erwartet.
; == Nun wollen wir testen, ob Peter darauf Zugriff hat. Das darf er ja nicht. Der Aufruf muß in diesem Fall "-1" zurückgeben.
ConsoleWrite(@CRLF & 'Peter versucht eine Pause anzusagen:' & @CRLF)
ConsoleWrite( _BAO_Class_ObjMethodCall($Peter, 'JustABreake') & @CRLF)
; == Und auch das klappt prima.
;====================================================================================================
; VERERBUNG
;====================================================================================================
; == Bis hierher waren das mehr oder weniger parametrisierte Funktionsaufrufe. Allerdings übersichtlicher, als wenn man nur die Funktionen ohne das Objekt-Modell nutzt.
; == Ein Wesenspunkt von Objekten ist die Vererbung. D.h., wenn ich ein Objekt als Abkömmling eines existierenden Objekts erstelle, besitzt dieses von vornherein dieselben
; == Methoden und Eigenschaften, wie das "Elternteil".
; == Wir haben z.Zt. eine Klasse "Programmierer"
; == Methoden: "DrinkCoffee" und "DoSomething"
; == Properties: "Arbeitsintensität" und "Kaffee-Konsum"
; == Jetzt erstellen wir eine neue Klasse "Codierer". Bei der Erstellung geben wir als Index die Klasse an, von der geerbt werden soll.
Global $Codierer = _BAO_Class_Create('Codierer', 'Programmierer')
; == Wir erstellen gleich ein Objekt dieser Klasse und testen, ob es auf die ererbten Methoden zugreifen kann
Global $Maria = _BAO_Class_ObjCreate($Codierer, 'Maria')
ConsoleWrite(@CRLF & 'Maria soll Kaffee trinken:' & @CRLF)
_BAO_Class_ObjMethodCall($Maria, 'DrinkCoffee')
ConsoleWrite(@CRLF & 'Maria soll arbeiten:' & @CRLF)
_BAO_Class_ObjMethodCall($Maria, 'DoSomething')
; == Das klappt, Maria als Mitglied der Klasse "Codierer" hat die Methoden von "Programmierer" geerbt
; == Nun noch die Prperties überprüfen
$aProps = _BAO_Class_ObjGet($Maria, 'props_g')
_ArrayDisplay($aProps, 'Props Maria')
; == Auch hier sind alle Eigenschaften vorhanden
BasicAutoItObjekt(v0.2)
#Region - TimeStamp
; 2012-04-23 15:48:35 v 0.2
#EndRegion - TimeStamp
#include-once
#include <Array.au3>
;====================================================================================================
; BAO = Basic-AutoIt-Object [ oder: BugFix-AutoIt-Object ;=) ]
;====================================================================================================
; FUNKTIONEN
; _BAO_Class_Create Erstellt eine Objekt-Klasse
; _BAO_Class_MethodSet Registriert eine Methode für die Klasse oder löscht sie
; _BAO_Class_PropSet Registriert, ändert oder löscht eine Property der Klasse
; _BAO_Class_ObjCreate Erstellt ein Klassen-Objekt oder löscht es aus der Klasse
; _BAO_Class_ObjMethodSet Registriert eine Methode für ein Klassen-Objekt oder löscht sie
; _BAO_Class_ObjPropSet Registriert, ändert oder löscht eine Property eines Klassen-Objektes
; _BAO_Class_ObjGet Abfragen von Informationen der Klasse und/oder des Klassen-Objektes
; _BAO_Class_ObjMethodCall Aufrufen von Methoden
;====================================================================================================
;===============================================================================
; Function Name....: _BAO_Class_Create
; Description......: Erstellt eine Objekt-Klasse
; Parameter(s).....: $_sClass Name der Klasse, die erstellt werden soll
; ........optional.: $_sIndexClass Name der Klasse, von der geerbt werden soll (Standard: 'self' = keine Vererbung)
; Requirement(s)...: Die Variable zum Aufnehmen des Objektes MUSS ZWINGEND identisch mit dem Klassennamen sein! ("$" & "Klassenname")
; Return Value(s)..: Array, das die Objekt-Klasse repräsentiert
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_Create($_sClass, $_sIndexClass='self')
Local Static $aClass_MethodsTmp, $aClass_PropsTmp, $sClassTmp
Local $aClass[4] ; == Array zum Speichern der Mitglieder der Klassenmerkmale: [Klassenname, Array-Methoden, Array-Properties, Array-KlassenObjekte]
If $_sIndexClass = 'self' Then
Local $aClass_Methods[1] = [0] ; == Array zur Aufnahme der Methoden, Erstellen mit Anzahl der akt. Methoden als erstem Element
Local $aClass_Props[1][2] = [[0]] ; == 2D-Array zur Aufnahme der Properties, Erstellen mit Anzahl der akt. Properties als erstem Element, [['property','value']]
Local $aMembers[1] = [0]
If IsArray($aClass_MethodsTmp) Then $aClass_Methods = $aClass_MethodsTmp
If IsArray($aClass_PropsTmp) Then $aClass_Props = $aClass_PropsTmp
If $sClassTmp <> '' Then $_sClass = $sClassTmp
$aClass[0] = $_sClass
$aClass[1] = $aClass_Methods
$aClass[2] = $aClass_Props
$aClass[3] = $aMembers
$aClass_MethodsTmp = ''
$aClass_PropsTmp = ''
$sClassTmp = ''
Return $aClass
Else
$sClassTmp = $_sClass ; == zu verwendender KlassenObjekt-Name
Local $aTmp = Execute('$' & $_sIndexClass) ; == alle zu vererbenden Informationen aus der "Index-Klasse" abfragen (Methoden und Eigenschaften)
$aClass_MethodsTmp = $aTmp[1]
$aClass_PropsTmp = $aTmp[2]
Return _BAO_Class_Create($_sClass)
EndIf
EndFunc ;==>_BAO_Class_Create
;===============================================================================
; Function Name....: _BAO_Class_MethodSet
; Description......: weist einer Klasse eine Methode oder löscht sie, gültig für alle Mitglieder der Klasse
; Parameter(s).....: $_aClass die mit "_BAO_Class_Create" erstellte Klasse
; .................: $_sMethod Name der Methode
;*********************************************************************************************************
; HINWEIS: Als erster Parameter sind ZWINGEND alle Methoden mit "$_self" zu versehen.
; In der Funktion zum Aufruf der Methode wird an diesen Paramter das aufrufende Objekt übergeben.
; Somit kann in den Methoden auf die Properties des KlassenObjektes zugegriffen werden.
; ZUSÄTZLICHE Parameter werden von der aufrufenden Funktion ("_BAO_Class_ObjMethodCall")
; IMMER als Array übergeben!!
;*********************************************************************************************************
; ........optional.: $iDelete "1" - Löscht die Methode aus der Klasse (Standard: 0, nicht Löschen)
; Return Value(s)..: Erfolg nichts
; .................: Fehler -1 set @error=1 - Methode kann nicht zugewiesen werden, existiert bereits
; .................: @error=2 - zu Löschende Methode ist nicht vorhanden
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_MethodSet(ByRef $_aClass, $_sMethod, $iDelete=0) ; == Parameter: Klassen-Array, Methode als String
Local $aMethods = $_aClass[1], $fFound = False ; == das Methoden-Array zum Bearbeiten aus dem Klassen-Array auslesen
If $aMethods[0] > 0 Then ; == suchen ob Methode vorhanden ==> dann Löschen
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
If $iDelete = 1 Then
_ArrayDelete($aMethods, $i)
$aMethods[0] -= 1
$_aClass[1] = $aMethods
Return
Else
Return SetError(1,0,-1)
EndIf
ExitLoop
EndIf
Next
If $iDelete = 1 And Not $fFound Then Return SetError(2,0,-1)
EndIf
$aMethods[0] += 1 ; == Anzahl Methoden um 1 erhöhen
ReDim $aMethods[$aMethods[0]+1] ; == Array vergrößern
$aMethods[$aMethods[0]] = $_sMethod ; == Methode eintragen
$_aClass[1] = $aMethods ; == bearbeitetes Methoden-Array zurückschreiben in Klassen-Array
EndFunc ;==>_BAO_Class_MethodSet
;===============================================================================
; Function Name....: _BAO_Class_PropSet
; Description......: Properties der Klasse Erstellen und/oder Ändern, Löschen, gültig für alle Mitglieder dieser Klasse
; Parameter(s).....: $_aClass die mit "_BAO_Class_Create" erstellte Klasse
; .................: $_sProp Name der Property
; ........optional.: $_vProp Wert der Property
; ........optional.: $iDelete "1" - Löscht die Property aus der Klasse (Standard: 0, nicht Löschen)
; Return Value(s)..: Erfolg nichts
; .................: Fehler -1 set @error=1 - zu Löschende Property ist nicht vorhanden
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_PropSet(ByRef $_aClass, $_sProp, $_vProp='', $iDelete=0) ; == Parameter: Klassen-Array, Eigenschaft als String, [optional] Wert der Eigenschaft
Local $aProps = $_aClass[2], $fFound = False ; == das Properties-Array zum Bearbeiten aus dem Klassen-Array auslesen
If $aProps[0][0] > 0 Then ; == suchen ob Property vorhanden ==> dann Aktualisieren od. Löschen
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sProp Then
$fFound = True
If $iDelete = 1 Then
_ArrayDelete($aProps, $i)
$aProps[0][0] -= 1
Else
$aProps[$i][1] = $_vProp
EndIf
ExitLoop
EndIf
Next
If $iDelete = 1 And Not $fFound Then Return SetError(1,0,-1)
If $fFound Then
$_aClass[2] = $aProps
Return
EndIf
EndIf
$aProps[0][0] += 1 ; == Anzahl Properties um 1 erhöhen
ReDim $aProps[$aProps[0][0]+1][2] ; == Array vergrößern
$aProps[$aProps[0][0]][0] = $_sProp ; == Eigenschaft eintragen
$aProps[$aProps[0][0]][1] = $_vProp ; == Wert eintragen
$_aClass[2] = $aProps ; == bearbeitetes Properties-Array zurückschreiben in Klassen-Array
EndFunc ;==>_BAO_Class_PropSet
;===============================================================================
; Function Name....: _BAO_Class_ObjCreate
; Description......: Erstellt ein Objekt einer Klasse oder löscht es aus der Klasse
; Parameter(s).....: $_aClass die mit "_BAO_Class_Create" erstellte Klasse
; .................: $_sName Name des KlassenObjektes
; ........optional.: $iDelete "1" - Löscht das Objekt aus der Klasse (Standard: 0, nicht Löschen)
; Requirement(s)...: Die Variable zum Aufnehmen des KlassenObjektes MUSS ZWINGEND identisch mit dem KlassenObjekt-Namen sein! ("$" & "KlassenObjekt-Name")
; Return Value(s)..: Erfolg Array, das das KlassenObjekt repräsentiert
; .................: Fehler -1 set @error=1 - Objekt kann nicht erstellt werden, existiert bereits
; .................: @error=2 - zu Löschendes Objekt ist nicht vorhanden
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_ObjCreate(ByRef $_aClass, $_sName, $iDelete=0) ; == Parameter: Klassen-Array, Name des Klassen-Objektes als String
Local $aClassObj_Methods[1] = [0] ; == Array zur Aufnahme der Methoden erstellen mit Anzahl der akt. Methoden als erstem Element
Local $aClassObj_Props[1][2] = [[0]] ; == 2D-Array zur Aufnahme der Properties erstellen mit Anzahl der akt. Properties als erstem Element, [['property','value']]
Local $objClass[4] = [$_sName, $_aClass[0], $aClassObj_Methods, $aClassObj_Props] ; == [Objektname, Klassenname, Array Objekt-Methoden, Array Objekt-Properties]
Local $aMembers = $_aClass[3], $fFound = False
If $aMembers[0] > 0 Then
For $i = 1 To $aMembers[0]
If $aMembers[$i] = $_sName Then
$fFound = True
If $iDelete = 1 Then
_ArrayDelete($aMembers, $i)
$aMembers[0] -= 1
$_aClass[3] = $aMembers
Return
Else
Return SetError(1,0,-1)
EndIf
ExitLoop
EndIf
Next
If $iDelete = 1 And Not $fFound Then Return SetError(2,0,-1)
EndIf
$aMembers[0] += 1
ReDim $aMembers[$aMembers[0]+1]
$aMembers[$aMembers[0]] = $_sName
$_aClass[3] = $aMembers
Return $objClass
EndFunc ;==>_BAO_Class_ObjCreate
;===============================================================================
; Function Name....: _BAO_Class_ObjMethodSet
; Description......: weist einem KlassenObjekt eine Methode zu oder löscht sie, gültig nur für dieses KlassenObjekt
; Parameter(s).....: $_objClass das mit "_BAO_Class_ObjCreate" erstellte KlassenObjekt
; .................: $_sMethod Name der Methode
;*********************************************************************************************************
; HINWEIS: Als erster Parameter sind ZWINGEND alle Methoden mit "$_self" zu versehen.
; In der Funktion zum Aufruf der Methode wird an diesen Paramter das aufrufende Objekt übergeben.
; Somit kann in den Methoden auf die Properties des KlassenObjektes zugegriffen werden.
; ZUSÄTZLICHE Parameter werden von der aufrufenden Funktion ("_BAO_Class_ObjMethodCall")
; IMMER als Array übergeben!!
; Methoden des KlassenObjektes werden beim Aufruf IMMER mit einem 2-ten Parameter, einem Array,
; aufgerufen. Dieses Array enthält an Array[0] ein Flag für das Überladen (0/1 = nein/ja).
; Um Fehler zu vermeiden einfach immer mit 2 Parametern deklarieren:
; Func MeineMethode($_self, $_aParam=0) <== so gibt es keine Fehler
;*********************************************************************************************************
; ........optional.: $iDelete "1" - Löscht die Methode aus dem KlassenObjekt (Standard: 0, nicht Löschen)
; Return Value(s)..: Erfolg nichts
; .................: Fehler -1 set @error=1 - Methode kann nicht zugewiesen werden, existiert bereits
; .................: @error=2 - zu Löschende Methode ist nicht vorhanden
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_ObjMethodSet(ByRef $_objClass, $_sMethod, $iDelete=0) ; == Parameter: Klassen-Objekt, Methode als String
Local $aMethods = $_objClass[2], $fFound = False ; == das Methoden-Array zum Bearbeiten aus dem KlassenObjekt-Array auslesen
If $aMethods[0] > 0 Then ; == suchen ob Methode vorhanden ==> dann Löschen
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
If $iDelete = 1 Then
_ArrayDelete($aMethods, $i)
$aMethods[0] -= 1
$_objClass[2] = $aMethods
Return
Else
Return SetError(1,0,-1)
EndIf
ExitLoop
EndIf
Next
If $iDelete = 1 And Not $fFound Then Return SetError(2,0,-1)
EndIf
$aMethods[0] += 1 ; == Anzahl Methoden um 1 erhöhen
ReDim $aMethods[$aMethods[0]+1] ; == Array vergrößern
$aMethods[$aMethods[0]] = $_sMethod ; == Methode eintragen
$_objClass[2] = $aMethods ; == bearbeitetes Methoden-Array zurückschreiben in KlassenObjekt-Array
EndFunc ;==>_BAO_Class_ObjMethodSet
;===============================================================================
; Function Name....: _BAO_Class_ObjPropSet
; Description......: Properties des KlassenObjektes Erstellen und/oder ändern, Löschen, gültig nur für dieses KlassenObjekt
; Parameter(s).....: $_objClass das mit "_BAO_Class_ObjCreate" erstellte KlassenObjekt
; .................: $_sProp Name der Property
; ........optional.: $_vProp Wert der Property
; ........optional.: $iDelete "1" - Löscht die Property aus dem KlassenObjekt (Standard: 0, nicht Löschen)
; Return Value(s)..: Erfolg nichts
; .................: Fehler -1 set @error=1 - zu Löschende Property ist nicht vorhanden
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_ObjPropSet(ByRef $_objClass, $_sProp, $_vProp='', $iDelete=0) ; == Parameter: KlassenObjekt, Eigenschaft als String, [optional] Wert der Eigenschaft
If Not IsArray($_objClass) Then $_objClass = Execute('$' & $_objClass)
Local $aProps = $_objClass[3], $fFound = False ; == das Properties-Array zum Bearbeiten aus dem KlassenObjekt-Array auslesen
If $aProps[0][0] > 0 Then ; == suchen ob Property vorhanden ==> dann Aktualisieren od. Löschen
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sProp Then
$fFound = True
If $iDelete = 1 Then
_ArrayDelete($aProps, $i)
$aProps[0][0] -= 1
Else
$aProps[$i][1] = $_vProp
EndIf
ExitLoop
EndIf
Next
If $iDelete = 1 And Not $fFound Then Return SetError(1,0,-1)
If $fFound Then
$_objClass[3] = $aProps
Return
EndIf
EndIf
$aProps[0][0] += 1 ; == Anzahl Properties um 1 erhöhen
ReDim $aProps[$aProps[0][0]+1][2] ; == Array vergrößern
$aProps[$aProps[0][0]][0] = $_sProp ; == Eigenschaft eintragen
$aProps[$aProps[0][0]][1] = $_vProp ; == Wert eintragen
$_objClass[3] = $aProps ; == bearbeitetes Properties-Array zurückschreiben in KlassenObjekt-Array
EndFunc ;==>_BAO_Class_ObjPropSet
;===============================================================================
; Function Name....: _BAO_Class_ObjGet
; Description......: Gibt Informationen zu einem KlassenObjekt/ der Klasse des Objektes zurück
; Parameter(s).....: $_objClass das mit "_BAO_Class_ObjCreate" erstellte KlassenObjekt (alternativ der Name des Objektes) oder die Klasse
; .................: $_sWhat welche Info wird angefordert
; .................: mögl. Werte:
; .................: "about" gibt alle vorhandenen Informationen zur Klasse aus als 2D-Array: [[name], [class], [Lokale_Meth,..,..], [Globale_Meth,..,..], [Lokale_Props,..,..], [Globale_Props,..,..], [Member,..]]
; .................: "count" gibt die Anzahl der Klassenmitglieder zurück
; .................: "members" gibt ein Array mit den Namen der Klassenmitglieder zurück
; .................: "name" gibt den Name des Klassenobjektes zurück
; .................: "class" gibt den Name der Klasse zurück
; .................: "methods_l" gibt ein Array aller Lokalen Methoden zurück
; .................: "methods_g" gibt ein Array aller Globalen Methoden zurück
; .................: "props_l" gibt ein 2D-Array aller Lokalen Properties zurück
; .................: "props_g" gibt ein 2D-Array aller Globalen Properties zurück
; .................: alles_andere Abfrage bezieht sich auf eine einzelne Property
; ........optional.: $_sAlternative wird eine abgefragte Property nicht gefunden, wird der hier hinterlegte Wert zurückgegeben (Standard: -1)
; Return Value(s)..: Ergebnis der Abfrage
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_ObjGet($_objClass, $_sWhat, $_sAlternative=-1) ; == Parameter: Klassen-Objekt, Abfragebegriff als String, "$_sAlternative": bei Abfrage einer Propertie - wenn nicht gefunden wird dieser Alternativwert zurückgegeben (Standard: -1)
Local $aClass = Execute('$' & Execute('$_objClass[1]')) ; == Zugriff auf das Klassenarray über den im Klassenobjekt hinterlegten Klassennamen [name, Array-Meth, Arr-Props, Array-Member]
Local $vRet, $aProps, $fFound = False, $aAbout[7][2], $aTmp, $fIsClass = False
If Not IsArray($aClass) Then
If IsArray($_objClass) Then
$fIsClass = True ; == $_objClass ist kein KlassenObjekt, sondern die Klasse selbst
Else
$_objClass = Execute('$' & $_objClass)
$aClass = Execute('$' & Execute('$_objClass[1]'))
EndIf
EndIf
Switch $_sWhat ; == was wird abgefragt
Case 'about' ; == Alle Informationen zum KlassenObjekt/ zur Klasse abfragen
If $fIsClass Then
ReDim $aAbout[4][2] ; == [Klassenname, Array-Methoden, Array-Properties, Array-KlassenObjekte]
$aAbout[0][0] = $_objClass[0] ; == Klassen-Name
$aTmp = $_objClass[1] ; == Globale Methoden
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[4][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[1][$i-1] = $aTmp[$i]
Next
EndIf
$aTmp = $_objClass[2] ; == Globale Properties (nur Namen, keine Werte)
If $aTmp[0][0] > 0 Then
If UBound($aAbout,2) < $aTmp[0][0] Then ReDim $aAbout[4][$aTmp[0][0]]
For $i = 1 To $aTmp[0][0]
$aAbout[2][$i-1] = $aTmp[$i][0]
Next
EndIf
$aTmp = $_objClass[3] ; == Member
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[3][$i-1] = $aTmp[$i]
Next
EndIf
Else
$aAbout[0][0] = $_objClass[0] ; == Objekt-Name
$aAbout[1][0] = $_objClass[1] ; == Klassen-Name
$aTmp = $_objClass[2] ; == Lokale Methoden
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[2][$i-1] = $aTmp[$i]
Next
EndIf
$aTmp = $aClass[1] ; == Globale Methoden
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[3][$i-1] = $aTmp[$i]
Next
EndIf
$aTmp = $_objClass[3] ; == Lokale Properties (nur Namen, keine Werte)
If $aTmp[0][0] > 0 Then
If UBound($aAbout,2) < $aTmp[0][0] Then ReDim $aAbout[6][$aTmp[0][0]]
For $i = 1 To $aTmp[0][0]
$aAbout[4][$i-1] = $aTmp[$i][0]
Next
EndIf
$aTmp = $aClass[2] ; == Globale Properties (nur Namen, keine Werte)
If $aTmp[0][0] > 0 Then
If UBound($aAbout,2) < $aTmp[0][0] Then ReDim $aAbout[6][$aTmp[0][0]]
For $i = 1 To $aTmp[0][0]
$aAbout[5][$i-1] = $aTmp[$i][0]
Next
EndIf
$aTmp = $aClass[3] ; == Member
If $aTmp[0] > 0 Then
If UBound($aAbout,2) < $aTmp[0] Then ReDim $aAbout[6][$aTmp[0]]
For $i = 1 To $aTmp[0]
$aAbout[6][$i-1] = $aTmp[$i]
Next
EndIf
EndIf
$vRet = $aAbout
Case 'count' ; == Anzahl der Mitglieder der Klasse ausgeben
If $fIsClass Then
$aTmp = $_objClass[3]
Return $aTmp[0]
EndIf
$aTmp = $aClass[3]
$vRet = $aTmp[0]
Case 'members' ; == Mitglieder der Klasse ausgeben (Array)
If $fIsClass Then Return $_objClass[3]
$aTmp = $aClass[3]
$vRet = $aTmp
Case 'name' ; == Name des KlassenObjektes ausgeben
If $fIsClass Then Return $_objClass[0] ; == bei Klasse, der Name der Klasse
$vRet = $_objClass[0]
Case 'class' ; == Name der Klasse ausgeben
If $fIsClass Then Return
$vRet = $_objClass[1]
Case 'methods_g' ; == das Methoden-Array aus dem Klassen-Array auslesen
If $fIsClass Then Return $_objClass[1]
$vRet = $aClass[1]
Case 'props_g' ; == das Properties-Array aus dem Klassen-Array auslesen
If $fIsClass Then Return $_objClass[2]
$vRet = $aClass[2]
Case 'methods_l' ; == das Methoden-Array aus dem KlassenObjekt-Array auslesen
If $fIsClass Then Return
$vRet = $_objClass[2]
Case 'props_l' ; == das Properties-Array aus dem KlassenObjekt-Array auslesen
If $fIsClass Then Return
$vRet = $_objClass[3]
Case Else ; == alles andere ist eine Abfrage zu einer einzelnen Eigenschaft (Lokal oder Global)
If Not $fIsClass Then
$aProps = $_objClass[3] ; == Priorität beachten, zuerst Lokal abfragen
If $aProps[0][0] > 0 Then
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sWhat Then
$vRet = $aProps[$i][1]
$fFound = True
ExitLoop
EndIf
Next
EndIf
EndIf
If Not $fFound Then
If $fIsClass Then
$aProps = $_objClass[2]
Else
$aProps = $aClass[2] ; == danach global abfragen
EndIf
If $aProps[0][0] > 0 Then
For $i = 1 To $aProps[0][0]
If $aProps[$i][0] = $_sWhat Then
$vRet = $aProps[$i][1]
$fFound = True
ExitLoop
EndIf
Next
EndIf
If Not $fFound Then $vRet = $_sAlternative ; == abgefragte Property gibt es nicht
EndIf
EndSwitch
Return $vRet
EndFunc ;==>_BAO_Class_ObjGet
;===============================================================================
; Function Name....: _BAO_Class_ObjMethodCall
; Description......: Aufruf von Methoden
; Parameter(s).....: $_objClass das mit "_BAO_Class_ObjCreate" erstellte KlassenObjekt
; .................: $_sMethod Name der Methode
; ........optional.: $_vParam Parameter, der übergeben werden soll (bei mehreren Parametern ein Array übergeben)
; Note.............: Diese Funktion übergibt IMMER als ersten Parameter den Namen des aufrufenden Objektes an die Methode.
; .................: Alle weiteren Parameter (auch wenn es nur einer ist) werden als ARRAY an die Methode übergeben.
; .................: Dies ist bei der Erstellung der Methoden unbedingt zu berücksichtigen.
; Return Value(s)..: Erfolg Der Rückgabewert der aufgerufenen Methode
; .................: Fehler -1 set @error=1
; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
;===============================================================================
Func _BAO_Class_ObjMethodCall(ByRef $_objClass, $_sMethod, $_vParam='')
Local $aParam[2] = [0], $fFound = False ; == $aParam wird als zweiter Parameter dem Aufruf übergeben, erstes Element =1 signalisiert Lokalen Aufruf
If Not IsArray($_objClass) Then $_objClass = Execute('$' & $_objClass)
If Not IsArray($_vParam) Then
$aParam[1] = $_vParam
Else
$aParam = $_vParam
_ArrayInsert($aParam, 0, 0)
EndIf
Local $aMethods = $_objClass[2] ; == zuerst bei den Lokalen Methoden nachschauen
If $aMethods[0] > 0 Then
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
$aParam[0] = 1 ; == Methode ist Lokal registriert, ParameterArray[0] = 1
ExitLoop
EndIf
Next
EndIf
If Not $fFound Then ; == dann bei den Globalen
Local $aClass = Execute('$' & Execute('$_objClass[1]'))
$aMethods = $aClass[1]
If $aMethods[0] > 0 Then
For $i = 1 To $aMethods[0]
If $aMethods[$i] = $_sMethod Then
$fFound = True
ExitLoop
EndIf
Next
EndIf
EndIf
If Not $fFound Then Return SetError(1,0,-1) ; == Aufruf enthält keine gültige Methode
If $_vParam = '' And $aParam[0] = 0 Then ; == kein Parameter übergeben, kein Lokaler Aufruf
Return Call($_sMethod, $_objClass) ; == evtl. Rückgabewert der Funktion wird ausgegeben
Else
Return Call($_sMethod, $_objClass, $aParam) ; == evtl. Rückgabewert der Funktion wird ausgegeben
EndIf
EndFunc ;==>_BAO_Class_ObjMethodCall
BAO_Bsp
#Region - TimeStamp
; 2012-04-23 15:41:21 v 0.1
#EndRegion - TimeStamp
#include "BasicAutoItObject.au3"
[/autoit] [autoit][/autoit] [autoit]; =========================================================================================================================================
; Einfaches Bsp. für Vererbung
; =========================================================================================================================================
; == Klasse Körper erstellen
; == gemeinsames Merkmal aller Körper: 3 Dimensionen
$Koerper = _BAO_Class_Create('Koerper')
_BAO_Class_PropSet($Koerper, 'dimension', 3)
; == Klasse Quader als Unterklasse der Körper erstellen, dazu wird als zweiter Parameter der Klassenname der 'Vaterklasse' übergeben
; == Merkmal von Quader: 6 Seiten
; == ererbt von Körper: 3 Dimensionen
$Quader = _BAO_Class_Create('Quader', 'Koerper')
_BAO_Class_PropSet($Quader, 'seiten', 6)
; == Ausgeben der Properties "dimension" und "seiten" der Klasse "Quader"
ConsoleWrite('Dimensionen (ererbt) von ' & _BAO_Class_ObjGet($Quader, 'name') & ': ' & _BAO_Class_ObjGet($Quader, 'dimension') & @CRLF)
ConsoleWrite('Seiten von ' & _BAO_Class_ObjGet($Quader, 'name') & ': ' & _BAO_Class_ObjGet($Quader, 'seiten') & @CRLF & @CRLF)
; == Klasse Würfel als Unterklasse von Quader
; == Merkmal von Würfel: Kantenlänge identisch
; == ererbt von Quader: 6 Seiten
; == (bereits ererbt von Körper: 3 Dimensionen)
$Wuerfel = _BAO_Class_Create('Wuerfel', 'Quader')
_BAO_Class_PropSet($Wuerfel, 'kantenlaenge', 'identisch')
; == Ausgeben der Properties "dimension", "seiten" und "kantenlaenge" der Klasse "Wuerfel"
ConsoleWrite('Dimensionen (ererbt) von ' & _BAO_Class_ObjGet($Wuerfel, 'name') & ': ' & _BAO_Class_ObjGet($Wuerfel, 'dimension') & @CRLF)
ConsoleWrite('Seiten (ererbt) von ' & _BAO_Class_ObjGet($Wuerfel, 'name') & ': ' & _BAO_Class_ObjGet($Wuerfel, 'seiten') & @CRLF)
ConsoleWrite('Kantenlänge von ' & _BAO_Class_ObjGet($Wuerfel, 'name') & ': ' & _BAO_Class_ObjGet($Wuerfel, 'kantenlaenge') & @CRLF & @CRLF)
; == allen Würfeln eine gemeinsame Methode zur Verfügung stellen
Func Wuerfeln($_self) ; == $_self ist immer als erster Parameter einer Methode anzugeben! An diesen Parameter wird beim Aufruf das aufrufende Objekt übergeben
Return '"' & _BAO_Class_ObjGet($_self, 'name') & '" würfelt eine: ' & Random(1,6,1)
EndFunc
_BAO_Class_MethodSet($Wuerfel, 'Wuerfeln')
[/autoit] [autoit][/autoit] [autoit]; == Objekte der Klasse Würfel erstellen
$Wuerfel_Holz = _BAO_Class_ObjCreate($Wuerfel, 'Wuerfel_Holz')
; == nur für dieses Objekt gültige Eigenschaft setzen
_BAO_Class_ObjPropSet($Wuerfel_Holz, 'material', 'Holz')
$Wuerfel_Alu = _BAO_Class_ObjCreate($Wuerfel, 'Wuerfel_Alu')
; == nur für dieses Objekt gültige Eigenschaft setzen
_BAO_Class_ObjPropSet($Wuerfel_Alu, 'material', 'Aluminium')
$Wuerfel_Plast = _BAO_Class_ObjCreate($Wuerfel, 'Wuerfel_Plast')
; == nur für dieses Objekt gültige Eigenschaft setzen
_BAO_Class_ObjPropSet($Wuerfel_Plast, 'material', 'Plastik')
; == Material aller Würfel-Objekte abfragen
$aMember = _BAO_Class_ObjGet($Wuerfel, 'members') ; == es kann auch ein Objekt der Klasse Würfel zur Abfrage verwendet werden, da die Gruppe 'members' identisch ist
If $aMember[0] > 0 Then
For $i = 1 To $aMember[0]
ConsoleWrite('Material von ' & _BAO_Class_ObjGet($aMember[$i], 'name') & ': ' & _BAO_Class_ObjGet($aMember[$i], 'material') & @CRLF)
Next
EndIf
ConsoleWrite(@CRLF)
; == die Methode "Wuerfeln" auf alle Würfel-Objekte anwenden, die bereits abgefragte Memberauflistung verwenden
For $i = 1 To $aMember[0]
ConsoleWrite( _BAO_Class_ObjMethodCall($aMember[$i], 'Wuerfeln') & @CRLF)
Next
; =========================================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]; =========================================================================================================================================
; Lange Funktionsnamen sind unhandlich, aber in der UDF erforderlich.
; Lösung: Für das Skript eigene Aufrufe schaffen.
; =========================================================================================================================================
; == Ich schaffe mir jetzt ausschließlich für mein Skript einen Funktionsraum, der auf der UDF basiert aber nur ganz kurze Funktionsnamen aufweist
#region - Funktionskonvertierung
; == Notation: C = Class; CO = ClassObject; M = Method; P = Property
; == _BAO_Class_Create => C_Create
Func C_Create($_1, $_2='self')
Return _BAO_Class_Create($_1, $_2)
EndFunc
; == _BAO_Class_MethodSet => C_Mset
Func C_Mset(ByRef $_1, $_2, $_3=0)
Return _BAO_Class_MethodSet($_1, $_2, $_3)
EndFunc
; == _BAO_Class_PropSet => C_Pset
Func C_Pset(ByRef $_1, $_2, $_3='', $_4=0)
Return _BAO_Class_PropSet($_1, $_2, $_3, $_4)
EndFunc
; == _BAO_Class_ObjCreate => CO_Create
Func CO_Create(ByRef $_1, $_2, $_3=0)
Return _BAO_Class_ObjCreate($_1, $_2, $_3)
EndFunc
; == _BAO_Class_ObjMethodSet => CO_Mset
Func CO_Mset(ByRef $_1, $_2, $_3=0)
Return _BAO_Class_ObjMethodSet($_1, $_2, $_3)
EndFunc
; == _BAO_Class_ObjPropSet => CO_Pset
Func CO_Pset(ByRef $_1, $_2, $_3='', $_4=0)
Return _BAO_Class_ObjPropSet($_1, $_2, $_3, $_4)
EndFunc
; == _BAO_Class_ObjGet => Get <== wird am häufigsten verwendet auch mehrfach in einer Befehlszeile, sollte deshalb besonders kurz und prägnant sein
Func Get($_1, $_2, $_3=-1)
Return _BAO_Class_ObjGet($_1, $_2, $_3)
EndFunc
; == _BAO_Class_ObjMethodCall => M_Call
Func M_Call($_1, $_2, $_3='')
Return _BAO_Class_ObjMethodCall($_1, $_2, $_3)
EndFunc
#endregion
; =========================================================================================================================================
; == nun verwende ich nur noch die konvertierten Aufrufe
; =========================================================================================================================================
; =========================================================================================================================================
; Beispiel für Überladen
; =========================================================================================================================================
#cs
Was ist Überladen?
Eine Klasse wird mit Methoden und Eigenschaften ausgestattet, die für alle Mitglieder der Klasse identisch sind.
Oft ist es aber sinnvoll für einzelne Mitglieder der Klasse diese Methoden/Eigenschaften zu individualisieren, evtl. auch nur vorübergehend.
D.h. dem einzelnen Mitglied der Klasse wird angewiesen, eine Methode anders auszuführen als die anderen Klassenmitglieder.
Da ich in AutoIt keine Lokalen Funktionen erstellen kann (Funktionen sind immer Global), muß ich mir hier anders behelfen.
Ich registriere die bereits für die Klasse registrierte Methode auch für das Klassenmitglied. Beim Aufruf der Methode durch das Klassenmitglied
wird zuerst geprüft ob die Methode für das Klassenmitglied selbst (also Lokal) registriert wurde. Ist das der Fall, wird dem Aufruf der Methode
zusätzlich ein Parameter übergeben, der signalisiert: Achtung! Abweichend vom Standard behandeln.
In der Methode wird dann auf diesen Parameter geprüft, ist er vorhanden erfolgt eine abweichende, "überladene" Abarbeitung der Methode.
#ce
; == Wir erstellen eine Klasse "Schüler"
$Schueler = C_Create('Schueler')
; == diese Klasse bekommt 2 Methoden
Func SagGutenMorgen($_self, $_aParam=0) ; == $_aParam enthält weiter Parameter, sofern übergeben; Bei Lokalem Aufruf wird $_aParam IMMER übergeben und bei Überladen ist $_aParam[0]=1
Local $fOverLoad = False
If IsArray($_aParam) Then ; == min. ein weiterer Parameter wurde übergebn
If $_aParam[0] = 1 Then $fOverLoad = True ; == die Methode wurde durch das aufrufende Mitglied überladen
EndIf
If $fOverLoad Then ; == Behandlung bei Überladen (wenn Überladen durch mehrere Mitglieder vorgesehen, einfach Switch mit $_self.name )
Local $Status = Get($_self, 'status_DE') ; == bisheriger Lernstatus
If $Status > 0 And $Status < 40 Then ; == der aktuelle Lernstatus muss 40 erreichen um keine extra Deutschstunde ableisten zu müssen, >0 da ohne Property -1 zurückgegeben wird
MsgBox(0, Get($_self, 'name'), 'Good Morning!'); == das normale Verhalten wird jetzt "Überladen" mit dem Mitglied-spezifischen Verhalten
Return M_Call($_self, 'LerneDeutsch') ; == eine extra Deutschstunde wird angeordnet und deren Ergebnis (neuer Status) an den Methodenaufruf zurückgegeben
EndIf
EndIf
MsgBox(0, Get($_self, 'name'), 'Guten Morgen!') ; == das ist das normale Verhalten der Methode
Return 0 ; == im Normallfall Rückgabe von "0", da Rückgabe des Lernerfolgs (bei Überladen) immer ">0"
EndFunc
Func LerneDeutsch($_self)
Local $Status = Get($_self, 'status_DE')
If $Status = -1 Then Return 100 ; == diese Eigenschaft ist für das Mitglied nicht gesetzt, als Kenntnisstand wird "100" zurückgegeben
Local $Lernfortschritt = Random(3,8,1) ; == Fortschritt des Lernens
Return $Status + $Lernfortschritt ; == Rückgabe neuer Status
EndFunc
; == die Methoden in der Klasse registrieren
C_Mset($Schueler, 'LerneDeutsch')
C_Mset($Schueler, 'SagGutenMorgen')
; == die allgemeingültige Eigenschaft
C_Pset($Schueler, 'religion', 'katholisch')
; == Jetzt brauchen wir Schüler, also Objekte dieser Klasse
$Peter = CO_Create($Schueler, 'Peter')
$Julia = CO_Create($Schueler, 'Julia')
$Mary = CO_Create($Schueler, 'Mary')
#cs
Nun wollen wir auch zusätzlich noch das Überladen von Eigenschaften mit betrachten. Die Klasse "Schüler" hat also z.B. die
Eigenschaft "Religion=katholisch", da die Schule von einer kath. Einrichtung betrieben wird.
Inzwischen hat sich die Schule aber weltoffen gestaltet und erlaubt auch den Zugang für Nichtkatholiken, allerdings ist dies nur vereinzelt
der Fall. Als Klasseneigenschaft wird also "Religion=katholisch" vorbesetzt, hat ein Schüler nicht diese Religion, erhält er die nur für ihn
gültige Eigenschaft "Religion=evangelisch" od. "Religion=ohne" etc. Die Eigenschaft "Religion" gibt es somit als individuelle und als
allgemeingültige Eigenschaft. Die individuelle (Lokale) Eigenschaft genießt eine höhere Priorität und "überlädt" somit die allgemeingültige (Globale) Eigenschaft.
#ce
; == Mary ist unsere Gastschülerin aus England - sie ist evangelisch und ihre Deutschkenntnisse lassen noch zu wünschen übrig
CO_Pset($Mary, 'religion', 'evangelisch') ; == hier überladen wir die Property "religion"
CO_Pset($Mary, 'status_DE', 30) ; == in dieser Property speichern wir Marys Deutschkenntnisse
; == Und da es anfangs mit der Sprache bei Mary hakt, müssen wir die Methode "SagGutenMorgen" überladen
CO_Mset($Mary, 'SagGutenMorgen') ; == Mary bekommt diese Methode separat zugewiesen, sie wird somit anders ausgeführt als beim Aufruf durch andere Klassenmitglieder
; == Nun wollen wir mal schauen, ob die Religion auch überladen wurde
; == Wir geben ein Array aller Mitglieder der Klasse Schüler aus und fragen für jedes Mitglied die Religion ab
$aMember = Get($Schueler, 'members')
For $i = 1 To $aMember[0]
ConsoleWrite('Religion von ' & Get($aMember[$i], 'name') & ': ' & Get($aMember[$i], 'religion') & @CRLF)
Next
; == OK, das funkltioniert
#cs
Nun noch das Überladen der Methode testen.
Die Methode "SagGutenMorgen" reagiert in Abhängigkeit zum aufrufenden Klassenmitglied. Von der Herangehensweise ist es nicht absolut
identisch mit einem tatsächlichen Überladen, aber der Effekt ist derselbe - und darauf kommt es an.
Unser Gast aus England ist am Anfang noch etwas schwach in Deutsch. Solange ihre Kenntnisse nicht mindestens einen Punktwert von 40 haben,
wird sie uns in englisch begrüßen und muß eine extra Stunde Deutschunterricht ableisten.
Erst wenn sie den Punktwert erreicht hat, braucht sie kein Deutsch zusätzlich lernen und die dann überflüssige Eigenschaft 'status_DE' wird
gelöscht.
#ce
; == Wir lassen uns erst mal von allen Mitgliedern der Klasse begrüßen
While 1
For $i = 1 To $aMember[0]
$ret = M_Call($aMember[$i], 'SagGutenMorgen')
If $ret > 0 Then ; == betrifft nur Mary
ConsoleWrite('Mary war zum Deutsch-Unterricht, neuer Lern-Status: ' & $ret & @CRLF)
If $ret > 39 Then ; == der erforderliche Lernstatus wurde erreicht
CO_Pset($Mary, 'status_DE', '', 1) ; == die Eigenschaft 'status_DE' wird nicht mehr benötigt und daher gelöscht
ExitLoop(2)
EndIf
CO_Pset($Mary, 'status_DE', $ret) ; == neuen Status in die Property eintragen
EndIf
Next
; == das wird solange wiederholt, bis Mary min. 40 Wissenspunkte hat
WEnd
; == Nun sollten uns alle Schüler auf Deutsch begrüßen
For $i = 1 To $aMember[0]
$ret = M_Call($aMember[$i], 'SagGutenMorgen')
Next
; == Wir haben also gesehen, dass sowohl Properties als auch Methoden überladen werden können.
[/autoit] [autoit][/autoit] [autoit]#cs
Die bisherige Lösung hat allerdings einen Schwachpunkt, den ich nicht verschweigen möchte:
Der Aufruf der Methoden wird mit dem AutoIt-Befehl "Call" veranlaßt. Dieser Befehl erlaubt aber nicht, Parameter ByRef zu übergeben.
Das ist ein großes Handicap. Dadurch kann ich über Methoden keine Veränderung von Properties vornehmen, da ich dazu einen referenzierten
Zugriff auf das entsprechende Klassenobjekt benötige.
Bsp.:
Die Methoden führen als ersten Parameter "$_self". Dieser Parameter wird von der Funktion zum MethodenCall an die Methode übergeben.
Da eine ByRef-Übergabe nicht möglich ist, wird dieser Parameter ByVal übergeben - also als Kopie. Somit kann ich die aktuellen Werte
des Klassenobjektes zwar auslesen, aber nicht ändern.
Dazu muß ich immer direkt die Original-Variable des Klassenobjekts verwenden.
#ce
Edit 23.04.2012
- In der UDF waren ein paar kleine Bugs - gefixed, aktuell: v0.2
- Beispieldatei erweitert um das Thema Überladen