OOP:Einsteiger OOP in AHK
Posted: 28 Jan 2018, 09:48
Übersetzt mit dem deepL.com Translator
Hallo,
in diesem Tutorial möchte ich klarstellen, was genau OOP ist, seine Vor- und Nachteile und einige einfache Tricks, wie man einfache OOP in AHK erstellt.
Generelles:
OOP ist ein Weg, um an die Programmierung heranzugehen. Viele Leute denken, dass es "nur die Verwendung der Klassensyntax ist, um etwas zu programmieren", aber das stimmt nicht im Geringsten.
In AHK ist man sogar in der Lage, gültigen OOP code zu erzeugen, ohne die Klassensyntax überhaupt zu verwenden. Allerdings ist das eher ungewöhnlich und ich werde nur die einfachste Methode erklären, die die besten Ergebnisse liefert.
Der Begriff OOP ist die Kurzform für objektorientierte Programmierung. Der Programmierbegriff des Objekts wurde Mitte der 60er Jahre erfunden.
Die objektorientierte Programmierung dreht sich um diese Objekte. Es hat sich Mitte der 90er Jahre zur Hauptprogrammiermethode entwickelt, und heutzutage gibt es nur noch wenige Sprachen ohne OOP.
OOP scheint zwar ein sehr definitiver Begriff zu sein, aber es gibt tatsächlich mehrere Möglichkeiten, wie man sich an OOP angehen kann, z.B. in AutoHotkey haben wir eine Prototypen-basierte Programmierung, aber ihr muss nicht genau wissen, was das bedeutet.
-> Wikipedia Prototypen Basiertes Programmieren ( im Englischen Artikel werden wir sogar erwähnt )
Warum sollte ich OOP verwenden?:
In der objektorientierten Programmierung und in der Prozeduralen Programmierung (wo man nur mit Funktionen arbeitet) teilt man Code in kleinere Teile, um ihn wiederzuverwenden. Der Unterschied, zwischen beiden, besteht darin, dass man in OOP auf mehrere Ebenen aufteilt.
Man hat mehrere erweiterte Möglichkeiten, den Code auf verschiedene Arten zu teilen, von einer sehr, sehr groben Ebene bis zur gleichen Detaillierungsstufe, die die Prozedurale Programmierung bietet.
Dies bietet viel mehr Möglichkeiten bei der Gestaltung des Projekts, das man erstellen möchte. Im Gegenzug braucht man diese Planungsphase wirklich oder man verliert sich einfach in den Möglichkeiten.
OOP bietet eine Vielzahl von Standard-Aktionen und Konventionen, die die Kommunikation von Code erheblich vereinfachen. Da es eng von der Logik der realen Welt abgeleitet ist, wird es wirklich intuitiv, sobald man sich daran gewöhnt hat.
Es ist auch einfacher, komplexe Vorgänge hinter einer leicht zugänglichen, intuitiven Oberfläche zu verbergen - was den Austausch von Code mit anderen wesentlich erleichtert. Man kann auch Kollisionsprobleme vermeiden.
Es ist auch einfacher, modulare Programme zu erstellen, bei denen große Teile des Codes problemlos ersetzt werden können - eine Notwendigkeit, wenn man den Code nach der Veröffentlichung warten möchte.
-> Diese Vor- und Nachteile sind sehr abstrakt, ich fasse zusammen, wozu sie führen:
OOP is besser:
Allgemeine Objekte vs. AutoHotkeys Objekte:
Objekte als Konzept innerhalb der Programmierung müssen ein paar Regeln erfüllen, um Objekte genannt zu werden:
Nicht alles, was im Kontext von AutoHotkey als Objekt bezeichnet wird, erfüllt die 1. oder 2. In diesem Tutorial werde ich nur über Objekte sprechen, die diese Regeln erfüllen, z. B:
Praktische Arbeit:
Nach vielen theoretischen Fakten über Objekte möchte ich diese Fakten in die Tat umsetzen und anhand eines praktischen Beispiels erläutern.
Ich denke, dass auf diese Weise mehr Leute dieses Tutorial verstehen könnten und es interessanter wäre.
Also werden wir einfach ein Beispielobjekt oder besser gesagt eine Beispiel-Klasse in AutoHotkey erstellen, die im OOP-Stil gehalten ist.
Für dieses Beispiel habe ich an das Dateisystem gedacht - also an Dateien, Verzeichnisse und Laufwerke.
Planungsphase:
Bevor wir mit der Erstellung eines Objektes beginnen, benötigen wir zunächst eine Planungsphase. Für diese Planungsphase nehmen Sie Stift und Papier - es ist nicht notwendig, aber es hilft enorm. ( Es hilft mir und meinem schrecklichen Gedächtnis zumindest. )
In OOP orientiert sich der Programmierer an Objekten, um zu programmieren. Da Sie jetzt Programmierer sind, müssen Sie genau das tun.
Der erste Schritt besteht also darin, die verschiedenen Objekttypen zu definieren, die Sie programmieren möchten. Das Thema, das wir gewählt haben, ist das Dateisystem und die Objekttypen hier sind Dateien, Verzeichnisse und Laufwerke.
Dann nehmen Sie ein Objekt und legen fest, welche Art von Informationen dieser Objekttyp enthält:
Initialisierungsstufe:
Wenn Sie eine neue Klasse für einen bestimmten Objekttyp erstellen, sollte der erste Schritt die Erstellung einer neuen AHK-Datei sein, die so benannt ist, wie die Klasse, die Sie erstellen möchten:
Also erstellen wir eine File.ahk. Danach wird einfach der Code für eine neue Klasse in die Klasse eingefügt:
Standardbegriffe und Aktionen von Objekten:
Unterbrechen wir das Programmieren kurz und kommen zurück zur Theorie. Es gibt mehrere Aktionen, die Sie auf jedes Objekt anwenden können.
Wenn diese Aktionen ausgeführt werden, wird eine bestimmte Methode innerhalb des Objekts aufgerufen.
Eine Methode ist im Grunde wie eine Funktion in einem Objekt, das aufgerufen wird.
Hier ist eine Liste von Dingen, die mit einem Objekt passieren können und welche Art von Methode sie aufrufen.
Es ist nicht wichtig zu verstehen, was sie alle im Moment tun - ich denke, dass man kaum in der Lage sein wird, aus dieser kurzen Liste heraus zu verstehen, was diese Methoden überhaupt tun.
Ich habe diese so bestellt, wie oft ich sie modifiziere. __New sollte ein Teil von fast jeder Klasse sein. __Delete ist nicht überall, aber es ist sehr verbreitet. __Get, __Set und __Call sind sehr mächtig, aber auch extrem anstrengend.
Anstatt ein neues _NewEnum() zu verwenden, werde ich oft eine Methode hinzufügen, um ein Array zu erhalten, das for-loopt so wie ich es will, da das einfacher ist.
Ich habe eigentlich noch nie zuvor __Init() benutzt, da ich stattdessen einfach __New verwenden kann und es nicht verwendet werden sollte.
Wenn Sie ein Objekt erstellen, sollten Sie sicherstellen, dass das Objekt, das Sie erstellt haben, über genügend Informationen verfügt, um gültig zu sein.
Das bedeutet, dass Sie, nachdem Sie ein neues File-Objekt aus unserer File-Klasse erstellt haben, in der Lage sein sollten, dessen Größe, Pfad... zu bestimmen.
Das bedeutet, dass wir für unser Beispiel die Informationen benötigen, die den Unterschied zwischen einer beliebigen Datei und einer bestimmten Datei ausmachen.
Für Dateien ist das ganz einfach - Sie haben einen Dateipfad, den nur diese Datei hat.
Für andere Objekte ist die Suche nach diesen Informationen etwas komplexer - Sie werden feststellen, dass es mehrere dieser Werte gibt oder dass Sie für einige dieser Werte Standardwerte verwenden können etc.
Für unser einfaches Beispiel sollte jedoch der Dateipfad ausreichen. Das Objekt benötigt diese Information beim Erstellen, daher benötigt es diese Information beim Aufruf von __New.
Um diesen Effekt zu erreichen, müssen wir der neuen Methode unseres Objekts und beim Erstellen mit dem new Operator einen Parameter hinzufügen:
Zurzeit haben wir diesen Code:und wenn wir hinzufügen, was wir über unsere __New Methode wissen:
Um eine gültiges File Objekt zu erstellen, müssen wir auch den fileName in dem Objekt speichern, das wir erstellen.
Dafür haben Methoden ein einfaches Feature. Das Objekt, mit dem sie aufgerufen werden, ist in ihnen vorhanden - es wird in der Variable this angeboten.
Zu Testzwecken habe ich einige Zeilen hinzugefügt, die ein Test File-Objekt erzeugen. Und Sie sollten das Problem wahrscheinlich schon hier sehen.
Die Datei existiert wahrscheinlich nicht auf Ihrem PC, aber wir haben ein Objekt erstellt, das gültig sein sollte - aber das ist es nicht, da die Datei nicht existiert.
Wir sollten wahrscheinlich prüfen, ob die Datei existiert, innerhalb der __New-Methode, und wir sollten auch prüfen, ob es sich um eine Datei handelt.Dies sollte verhindern, dass ein ungültiges Objekt erzeugt wird.
Es gibt 2 Möglichkeiten, dies zu tun. Eine davon ist die Verwendung von Properties. Die andere ist die Verwendung von Gettern.
Properties are special to AutoHotkey Objects where a piece of code is triggered when you try to set or get a specific key of an object.
Getters sind nur Methoden, bei denen der Name des Attributs, das Sie erhalten möchten, mit get vorangestellt wird, z. B. file.getFullPath().
Sie können beides benutzen, so oder so ist es gut. Allerdings bevorzuge ich Getter, da sie in vielen Sprachen gebräuchlich sind. Ich werde getters für dieses Tutorial verwenden.
Testen wir es noch einmal. Wir werden eine test.ahk im selben Ordner wie unsere File.ahk ablegen:
Wenn Sie diesen Code ausführen, sollten Sie ein Problem sehen. Wenn wir versuchen, das enthaltende Verzeichnis unseres zweiten File-Objekts zu erhalten, bekommen wir kein Verzeichnis.
Dies ist auf eine Einschränkung innerhalb von SplitPath zurückzuführen. SplitPath gibt das Verzeichnis nur dann zurück, wenn es Teil des angegebenen Dateipfades war.
Der Dateipfad, den wir in unserem zweiten Objekt gespeichert haben, ist "File.ahk" - er enthält keinen Pfad zum Verzeichnis, was es SplitPath unmöglich macht, diesen zurückzugeben.
Die Lösung besteht darin, entweder relative Pfade zu verbieten oder jede Art von Pfad, der dem Objekt gegeben wird, in einen vollständigen Pfad aufzulösen.
Wenn Sie relative Pfade verbieten, werden die Anwendungsmöglichkeiten unserer Klasse reduziert, und Sie müssen herausfinden, ob der Pfad relativ ist oder nicht.
Das Auflösen des Pfades zu einem vollen Pfad ist ziemlich einfach und macht unsere Klasse mächtiger. Sie können die Datei-Schleife innerhalb des Konstruktors verwenden, um dies zu erreichen:
Wenn wir unsere test.ahk ausführen, nachdem wir File.ahk geändert haben, sollten wir die richtigen Ergebnisse erhalten.
Getters, Setter und Delegation:
Nachdem wir Ihre erste Klasse erstellt und 2 Instanzen dieser Klasse erstellt haben, sollten wir einen Schritt zurücktreten und die Regeln überprüfen, die unser Objekt erfüllen muss, um OOP zu sein:
Der nächste Schritt, den wir machen müssen, ist, dem Benutzer dieser Klasse die Möglichkeit zu geben, die Attribute dieser Datei zu ändern.
Im einfachsten Fall fügen Sie einen Setter hinzu. Ein Setter ist wie ein Getter, nur dass er statt eines Attributs das Attribut eines Objekts setzt.
Setter können verwendet werden, solange es einen einzigen, definierten Weg gibt, um das Attribut zu setzen sowie das Setzen des Attributs auf seinen entsprechenden Get-Wert des selben Objektes keine Änderung im Objekt bewirkt.
Überprüfen wir die Attribute, die wir haben:
Für unsere Inhalte setzen wir Delegation ein. Auf einer allgemeineren Ebene ist Delegation die Handlung, jemanden oder etwas anderes dazu zu bringen, Ihre Arbeit zu tun.
Wenn Sie ein Objekt programmieren und feststellen, dass es bereits ein Objekt gibt, das einen Teil Ihrer Arbeit erledigt, dann können Sie dieses Objekt verwenden und den Job an dieses Objekt zu delegieren.
Sie könnten auch Delegation verwenden, wenn Sie der Meinung sind, dass Sie viele Methoden haben, die spezifisch für einen einzelnen Attributtyp sind, der Ihr Objekt unübersichtlich macht. - z.B. unser Pfad mit allem getPath() getPathName()......
Wir werden uns jedoch darauf konzentrieren, die Aufgabe der Verwaltung des Dateiinhalts an AutoHotkeys zu delegieren, die inm File-Objekt integriert sind. Ich meine, dafür ist es doch gut, oder?
Das bedeutet, dass wir eine Methode benötigen, die ein neues AHK File-Objekt in unserer File-Klasse zurückgibt. Nennen wir es open()
Wir fügen auch eine weitere Methode für die letzte Aktion hinzu, die wir auf unsere Datei anwenden können (Löschen der Datei) und nennen sie delete().
Damit müssen wir die folgenden Methoden hinzufügen:
Für mich ist das genug, um das Objekt komplett auswendig zu lernen. Ich habe ständig eine Liste aller Objekte und deren Methoden vor mir.
Das hat mir durch viele Situationen geholfen und mein Leben als Entwickler so viel einfacher gemacht.
Die letzte praktische Arbeit an der File Class:
Sie sollten wahrscheinlich in der Lage sein, alle Änderungen, die an dem FileObject vorgenommen werden müssen, selber zu implementieren.
Aber hier ist das Endresultat:
Zusammenfassung:
In diesem Teil des Tutorials haben wir gelernt:
Hallo,
in diesem Tutorial möchte ich klarstellen, was genau OOP ist, seine Vor- und Nachteile und einige einfache Tricks, wie man einfache OOP in AHK erstellt.
Generelles:
OOP ist ein Weg, um an die Programmierung heranzugehen. Viele Leute denken, dass es "nur die Verwendung der Klassensyntax ist, um etwas zu programmieren", aber das stimmt nicht im Geringsten.
In AHK ist man sogar in der Lage, gültigen OOP code zu erzeugen, ohne die Klassensyntax überhaupt zu verwenden. Allerdings ist das eher ungewöhnlich und ich werde nur die einfachste Methode erklären, die die besten Ergebnisse liefert.
Der Begriff OOP ist die Kurzform für objektorientierte Programmierung. Der Programmierbegriff des Objekts wurde Mitte der 60er Jahre erfunden.
Die objektorientierte Programmierung dreht sich um diese Objekte. Es hat sich Mitte der 90er Jahre zur Hauptprogrammiermethode entwickelt, und heutzutage gibt es nur noch wenige Sprachen ohne OOP.
OOP scheint zwar ein sehr definitiver Begriff zu sein, aber es gibt tatsächlich mehrere Möglichkeiten, wie man sich an OOP angehen kann, z.B. in AutoHotkey haben wir eine Prototypen-basierte Programmierung, aber ihr muss nicht genau wissen, was das bedeutet.
-> Wikipedia Prototypen Basiertes Programmieren ( im Englischen Artikel werden wir sogar erwähnt )
Warum sollte ich OOP verwenden?:
In der objektorientierten Programmierung und in der Prozeduralen Programmierung (wo man nur mit Funktionen arbeitet) teilt man Code in kleinere Teile, um ihn wiederzuverwenden. Der Unterschied, zwischen beiden, besteht darin, dass man in OOP auf mehrere Ebenen aufteilt.
Man hat mehrere erweiterte Möglichkeiten, den Code auf verschiedene Arten zu teilen, von einer sehr, sehr groben Ebene bis zur gleichen Detaillierungsstufe, die die Prozedurale Programmierung bietet.
Dies bietet viel mehr Möglichkeiten bei der Gestaltung des Projekts, das man erstellen möchte. Im Gegenzug braucht man diese Planungsphase wirklich oder man verliert sich einfach in den Möglichkeiten.
OOP bietet eine Vielzahl von Standard-Aktionen und Konventionen, die die Kommunikation von Code erheblich vereinfachen. Da es eng von der Logik der realen Welt abgeleitet ist, wird es wirklich intuitiv, sobald man sich daran gewöhnt hat.
Es ist auch einfacher, komplexe Vorgänge hinter einer leicht zugänglichen, intuitiven Oberfläche zu verbergen - was den Austausch von Code mit anderen wesentlich erleichtert. Man kann auch Kollisionsprobleme vermeiden.
Es ist auch einfacher, modulare Programme zu erstellen, bei denen große Teile des Codes problemlos ersetzt werden können - eine Notwendigkeit, wenn man den Code nach der Veröffentlichung warten möchte.
-> Diese Vor- und Nachteile sind sehr abstrakt, ich fasse zusammen, wozu sie führen:
OOP is besser:
- für größere Projekte
- wenn man mit mehreren Leuten arbeitet
- für Code den man wiederverwenden möchte
- für Code den man teilen möchte
Code: Select all
[*]du in der Zukunft Entwickler werden willst
[*]du gerne code mit anderen teilst
[*]du ein Entwickler werden willst - da es der verbreitetste Coding Standard in der Industrie ist
Objekte als Konzept innerhalb der Programmierung müssen ein paar Regeln erfüllen, um Objekte genannt zu werden:
- Ein Objekt ist mehr als einfache Daten und mehr als Funktionalität - es ist immer beides. Ein Objekt sind die Daten und die Modifikationen, die Sie an diesen Daten vornehmen können.
- Ein Objekt ist immer die Instanz einer Klasse. Eine Klasse definiert die Datenstruktur und die Modifikationen, die Sie an dieser Datenstruktur vornehmen können.
- Ein Objekt schützt seine internen Abläufe vor dem Zugriff von außen und erlaubt nur bestimmte Aktionen und Modifikationen von außen.
Nicht alles, was im Kontext von AutoHotkey als Objekt bezeichnet wird, erfüllt die 1. oder 2. In diesem Tutorial werde ich nur über Objekte sprechen, die diese Regeln erfüllen, z. B:
Code: Select all
class ObjectClass {
}
object := new ObjectClass() ;wobei object ein Objekt ist, das die Regeln 1 und 2 erfüllt und Regel 3 niemals gebrochen wird
;1 es hat leere Daten und die Möglichkeiten, diese Daten zu ändern, sind nicht vorhanden.
;2 ist es die Instanz der Klasse ObjectClass, die definiert, dass dieses Objekt weder über eine Datenstruktur noch über Modifikationsmöglichkeiten verfügt.
;3, da wir nie auf das Objekt in irgendeiner Weise zugreifen, die es nicht beabsichtigt war - daher ist Regel 3 nie gebrochen und somit erfüllt.
Nach vielen theoretischen Fakten über Objekte möchte ich diese Fakten in die Tat umsetzen und anhand eines praktischen Beispiels erläutern.
Ich denke, dass auf diese Weise mehr Leute dieses Tutorial verstehen könnten und es interessanter wäre.
Also werden wir einfach ein Beispielobjekt oder besser gesagt eine Beispiel-Klasse in AutoHotkey erstellen, die im OOP-Stil gehalten ist.
Für dieses Beispiel habe ich an das Dateisystem gedacht - also an Dateien, Verzeichnisse und Laufwerke.
Planungsphase:
Bevor wir mit der Erstellung eines Objektes beginnen, benötigen wir zunächst eine Planungsphase. Für diese Planungsphase nehmen Sie Stift und Papier - es ist nicht notwendig, aber es hilft enorm. ( Es hilft mir und meinem schrecklichen Gedächtnis zumindest. )
In OOP orientiert sich der Programmierer an Objekten, um zu programmieren. Da Sie jetzt Programmierer sind, müssen Sie genau das tun.
Der erste Schritt besteht also darin, die verschiedenen Objekttypen zu definieren, die Sie programmieren möchten. Das Thema, das wir gewählt haben, ist das Dateisystem und die Objekttypen hier sind Dateien, Verzeichnisse und Laufwerke.
Dann nehmen Sie ein Objekt und legen fest, welche Art von Informationen dieser Objekttyp enthält:
was ich wie folgt aufschreiben werde:files - haben einen Namen
...
Für den Einsteiger Kurs werden wir direkt zum Programmieren gehen.files:
-path (... und die ganzen anderen Pfad arten wie z.B. Extension)
-content ( Inhalt der Datei )
--size ( Es ist zwar die size des contents aber man kann es trotzdem direkt ausgeben )
-attributes ( z. B. ReadOnly etc. )
-time ( letzte Zugriffszeit etc. )
Initialisierungsstufe:
Wenn Sie eine neue Klasse für einen bestimmten Objekttyp erstellen, sollte der erste Schritt die Erstellung einer neuen AHK-Datei sein, die so benannt ist, wie die Klasse, die Sie erstellen möchten:
Also erstellen wir eine File.ahk. Danach wird einfach der Code für eine neue Klasse in die Klasse eingefügt:
Code: Select all
class File {
}
Unterbrechen wir das Programmieren kurz und kommen zurück zur Theorie. Es gibt mehrere Aktionen, die Sie auf jedes Objekt anwenden können.
Wenn diese Aktionen ausgeführt werden, wird eine bestimmte Methode innerhalb des Objekts aufgerufen.
Eine Methode ist im Grunde wie eine Funktion in einem Objekt, das aufgerufen wird.
Hier ist eine Liste von Dingen, die mit einem Objekt passieren können und welche Art von Methode sie aufrufen.
Es ist nicht wichtig zu verstehen, was sie alle im Moment tun - ich denke, dass man kaum in der Lage sein wird, aus dieser kurzen Liste heraus zu verstehen, was diese Methoden überhaupt tun.
- Erstellen eines Objekts __New( 0-x creation parameters )
- Löschen eines Objekts __Delete()
- Zugriff auf inexistenten Schlüssel __Get( 1-x keynames )
- Setzen eines inexistenten Schlüssels __Set( 1-x keynames, setValue )
- Aufruf einer Methode __Call( methodName, parameters )
- Benutzen des For-Loops _NewEnum()
- Vor __New gibt es __Init()
Ich habe diese so bestellt, wie oft ich sie modifiziere. __New sollte ein Teil von fast jeder Klasse sein. __Delete ist nicht überall, aber es ist sehr verbreitet. __Get, __Set und __Call sind sehr mächtig, aber auch extrem anstrengend.
Anstatt ein neues _NewEnum() zu verwenden, werde ich oft eine Methode hinzufügen, um ein Array zu erhalten, das for-loopt so wie ich es will, da das einfacher ist.
Ich habe eigentlich noch nie zuvor __Init() benutzt, da ich stattdessen einfach __New verwenden kann und es nicht verwendet werden sollte.
Wenn Sie ein Objekt erstellen, sollten Sie sicherstellen, dass das Objekt, das Sie erstellt haben, über genügend Informationen verfügt, um gültig zu sein.
Das bedeutet, dass Sie, nachdem Sie ein neues File-Objekt aus unserer File-Klasse erstellt haben, in der Lage sein sollten, dessen Größe, Pfad... zu bestimmen.
Das bedeutet, dass wir für unser Beispiel die Informationen benötigen, die den Unterschied zwischen einer beliebigen Datei und einer bestimmten Datei ausmachen.
Für Dateien ist das ganz einfach - Sie haben einen Dateipfad, den nur diese Datei hat.
Für andere Objekte ist die Suche nach diesen Informationen etwas komplexer - Sie werden feststellen, dass es mehrere dieser Werte gibt oder dass Sie für einige dieser Werte Standardwerte verwenden können etc.
Für unser einfaches Beispiel sollte jedoch der Dateipfad ausreichen. Das Objekt benötigt diese Information beim Erstellen, daher benötigt es diese Information beim Aufruf von __New.
Um diesen Effekt zu erreichen, müssen wir der neuen Methode unseres Objekts und beim Erstellen mit dem new Operator einen Parameter hinzufügen:
Code: Select all
class Beispiel {
__New( beispielInfo ) {
Msgbox % beispielInfo
}
}
test := new Besipiel( "Test" )
Bug Warnung
Zurück in unsere Klasse:Zurzeit haben wir diesen Code:
Code: Select all
class File {
}
Code: Select all
class File {
__New( fileName ) {
}
}
Dafür haben Methoden ein einfaches Feature. Das Objekt, mit dem sie aufgerufen werden, ist in ihnen vorhanden - es wird in der Variable this angeboten.
Code: Select all
class File {
__New( fileName ) {
this.name := fileName
}
}
abc := new File( "D:\Test.ahk" ) ;zum Testen
Msgbox % abc.name ;auch zum Testen
Die Datei existiert wahrscheinlich nicht auf Ihrem PC, aber wir haben ein Objekt erstellt, das gültig sein sollte - aber das ist es nicht, da die Datei nicht existiert.
Wir sollten wahrscheinlich prüfen, ob die Datei existiert, innerhalb der __New-Methode, und wir sollten auch prüfen, ob es sich um eine Datei handelt.
Code: Select all
class File {
__New( fileName ) {
if ( !fileExist( fileName ) )
Msgbox Datei existiert nicht : "%fileName%"
if ( inStr( fileExist( fileName ), "D" ) ) ;Wenn fileName auf einen Ordner oder ein Laufwerk verweist
Msgbox Datei ist keine valide Datei
this.name := fileName
}
}
Was tun, wenn die Objekterstellung fehlschlägt?
Der nächste Schritt ist das Hinzufügen von Funktionalität, die es erlaubt alle Informationen, die wir aus dieser Datei erhalten können, abrufen kann. Es gibt 2 Möglichkeiten, dies zu tun. Eine davon ist die Verwendung von Properties. Die andere ist die Verwendung von Gettern.
Properties are special to AutoHotkey Objects where a piece of code is triggered when you try to set or get a specific key of an object.
Getters sind nur Methoden, bei denen der Name des Attributs, das Sie erhalten möchten, mit get vorangestellt wird, z. B. file.getFullPath().
Sie können beides benutzen, so oder so ist es gut. Allerdings bevorzuge ich Getter, da sie in vielen Sprachen gebräuchlich sind. Ich werde getters für dieses Tutorial verwenden.
Code: Select all
class File {
__New( fileName ) {
if ( !fileExist( fileName ) )
Msgbox Datei existiert nicht : "%fileName%"
if ( inStr( fileExist( fileName ), "D" ) ) ;Wenn fileName auf einen Ordner oder ein Laufwerk verweist
Msgbox Datei ist keine valide Datei
this.name := fileName
}
getPath() {
return this.name
}
getPathName() {
SplitPath, % this.name, fileName
return fileName
}
getPathDir() { ;das selbe wie getDirectory
return This.getPathDirectory()
}
getPathDirectory() {
SplitPath, % this.name, , fileDirectory
return fileDirectory
}
getPathExtension() {
SplitPath, % this.name , , , fileExtension
return fileExtension
}
getPathNameNoExtension() {
SplitPath, % this.name, , , , fileNameNoExtension
return fileNameNoExtension
}
getPathDrive() {
SplitPath, % this.name, , , , , fileDrive
return fileDrive
}
getSize( unit := "" ) {
FileGetSize, fileSize, % this.name, % unit
return fileSize
}
getAttributes() { ;ein flag string siehe AutoHotkey Hilfe
return FileExist( this.name )
}
getTimeAccessed() { ;in YYYYMMDDHH24MISS siehe AutoHotkey Hilfe für mehr Details
FileGetTime, timeCreated, % this.name, A
return timeCreated
}
getTimeModified() {
FileGetTime, timeCreated, % this.name, M
return timeCreated
}
getTimeCreated() {
FileGetTime, timeCreated, % this.name, C
return timeCreated
}
}
Code: Select all
#Include File.ahk
file1 := new File( A_ScriptFullPath ) ;ein File Objekt unserer test.ahk
file2 := new File( "File.ahk" ) ;ein File Objekt unserer File.ahk
Msgbox % file1.getPathDir() ;Den enthaltenden Ordner zurück geben
Msgbox % file2.getPathDir() ;Den enthaltenden Ordner zurück geben
Dies ist auf eine Einschränkung innerhalb von SplitPath zurückzuführen. SplitPath gibt das Verzeichnis nur dann zurück, wenn es Teil des angegebenen Dateipfades war.
Der Dateipfad, den wir in unserem zweiten Objekt gespeichert haben, ist "File.ahk" - er enthält keinen Pfad zum Verzeichnis, was es SplitPath unmöglich macht, diesen zurückzugeben.
Die Lösung besteht darin, entweder relative Pfade zu verbieten oder jede Art von Pfad, der dem Objekt gegeben wird, in einen vollständigen Pfad aufzulösen.
Wenn Sie relative Pfade verbieten, werden die Anwendungsmöglichkeiten unserer Klasse reduziert, und Sie müssen herausfinden, ob der Pfad relativ ist oder nicht.
Das Auflösen des Pfades zu einem vollen Pfad ist ziemlich einfach und macht unsere Klasse mächtiger. Sie können die Datei-Schleife innerhalb des Konstruktors verwenden, um dies zu erreichen:
Code: Select all
...
__New( fileName ) {
if ( !fileExist( fileName ) )
Msgbox Datei existiert nicht : "%fileName%"
if ( inStr( fileExist( fileName ), "D" ) ) ;Wenn fileName auf einen Ordner oder ein Laufwerk verweist
Msgbox Datei ist keine valide Datei
Loop, Files, % fileName, F ;Da sich der Dateiname auf eine einzelne Datei bezieht, wird diese Schleife nur einmal ausgeführt.
this.name := A_LoopFileLongPath ;und hier wird er den Pfad auf den Wert setzen, den wir brauchen.
}
...
Getters, Setter und Delegation:
Nachdem wir Ihre erste Klasse erstellt und 2 Instanzen dieser Klasse erstellt haben, sollten wir einen Schritt zurücktreten und die Regeln überprüfen, die unser Objekt erfüllen muss, um OOP zu sein:
- Ein Objekt ist mehr als nur einfache Daten oder Funktionalität, denn es ist immer beides. Ein Objekt ist die Daten, die Zugriffsmöglichkeiten auf diese Daten und die Modifikationen, die Sie an diesen Daten vornehmen können.
-> Die Daten sind der Dateipfad. Und bisher haben wir nur Möglichkeiten, auf die Daten der jeweiligen Datei zuzugreifen. OK - Ein Objekt ist immer die Instanz einer Klasse. Eine Klasse definiert die Datenstruktur und die Modifikationen, die Sie an dieser Datenstruktur vornehmen können.
-> Wir verwenden eine Klasse, um dieses Objekt zu definieren, seine Datenstruktur und die Zugriffsmöglichkeiten darauf. OK - Ein Objekt schützt seine internen Abläufe vor dem Zugriff von außen und erlaubt nur bestimmte Aktionen und Modifikationen von außen.
-> Wie wir bereits gesagt haben, ist diese Art von Regel in AutoHotkey schwer zu erfüllen. Solange Sie dieses Objekt so verwenden, wie es beabsichtigt war - also nur erstellen oder getters verwenden - ist es so, als ob es eine Grenze gäbe und wir erfüllen diese Regel OK.
Der nächste Schritt, den wir machen müssen, ist, dem Benutzer dieser Klasse die Möglichkeit zu geben, die Attribute dieser Datei zu ändern.
Im einfachsten Fall fügen Sie einen Setter hinzu. Ein Setter ist wie ein Getter, nur dass er statt eines Attributs das Attribut eines Objekts setzt.
Setter können verwendet werden, solange es einen einzigen, definierten Weg gibt, um das Attribut zu setzen sowie das Setzen des Attributs auf seinen entsprechenden Get-Wert des selben Objektes keine Änderung im Objekt bewirkt.
Überprüfen wir die Attribute, die wir haben:
- Path - der Pfad kann entweder durch Kopieren oder Verschieben der Datei geändert werden, da dies kein einziger Weg ist, den wir hier nicht benutzen können.
- Attributes - wenn Sie versuchen, Attribute mit FileSetAttrib zu setzen, müssen Sie beschreiben, wie die Attribute geändert werden sollen, nicht wie sie am Ende aussehen sollen.
Generell ist es möglich, hier einen Setter zu verwenden. Aber wir müssen die Befehle FileGetAttrib und FileSetAttrib so umschließen, dass der Getter-Wert in der Setter-Methode verwendet werden kann, ohne Änderungen am Objekt zu verursachen.
Das wäre lästig. Oder besser gesagt, es ist Arbeit und generell wollen wir nicht viel unnötige Mehrarbeit. - Time - die Art und Weise, wie die Zeit eingestellt wird, ist einzigartig, definiert und die Eingabe des Get-Wertes in den Setter ändert die Datei nicht - wir können hier einen Setter verwenden.
- Size - Die Größenänderung einer Datei ist unterdefiniert, die Größenänderung ändert den Inhalt und die Bearbeitung des Inhalts ist etwas, was wir noch nicht besprochen haben.
- Content - Wir haben das alles aus einem bestimmten Grund nicht besprochen.
Für unsere Inhalte setzen wir Delegation ein. Auf einer allgemeineren Ebene ist Delegation die Handlung, jemanden oder etwas anderes dazu zu bringen, Ihre Arbeit zu tun.
Wenn Sie ein Objekt programmieren und feststellen, dass es bereits ein Objekt gibt, das einen Teil Ihrer Arbeit erledigt, dann können Sie dieses Objekt verwenden und den Job an dieses Objekt zu delegieren.
Sie könnten auch Delegation verwenden, wenn Sie der Meinung sind, dass Sie viele Methoden haben, die spezifisch für einen einzelnen Attributtyp sind, der Ihr Objekt unübersichtlich macht. - z.B. unser Pfad mit allem getPath() getPathName()......
Wir werden uns jedoch darauf konzentrieren, die Aufgabe der Verwaltung des Dateiinhalts an AutoHotkeys zu delegieren, die inm File-Objekt integriert sind. Ich meine, dafür ist es doch gut, oder?
Das bedeutet, dass wir eine Methode benötigen, die ein neues AHK File-Objekt in unserer File-Klasse zurückgibt. Nennen wir es open()
Wir fügen auch eine weitere Methode für die letzte Aktion hinzu, die wir auf unsere Datei anwenden können (Löschen der Datei) und nennen sie delete().
Damit müssen wir die folgenden Methoden hinzufügen:
Jetzt holen wir wieder Stift und Papier und schreiben und alle Methoden unseres Objektes neben dem dazugehörigen Attribut auf:setTimeModified( time ), setTimeAccessed( time ), setTimeCreated( time )
copy( filePath ), move( filePath )
changeAttributes( changeAttributesString )
open( mode, encoding := A_FileEncoding )
Der Punkt dabei ist, dass Sie nun eine vollständige Liste aller Methoden Ihres Objekts haben, mit denen Sie es von außen modifizieren können.files: __new( fileName )
path: get*(), move( filePath, overwrite ), copy( filePath )
content: open( mode, encoding )
size: get*( unit )
attributes: get*(), change*( changes )
time: get*() set*()
delete()
Für mich ist das genug, um das Objekt komplett auswendig zu lernen. Ich habe ständig eine Liste aller Objekte und deren Methoden vor mir.
Das hat mir durch viele Situationen geholfen und mein Leben als Entwickler so viel einfacher gemacht.
Die letzte praktische Arbeit an der File Class:
Sie sollten wahrscheinlich in der Lage sein, alle Änderungen, die an dem FileObject vorgenommen werden müssen, selber zu implementieren.
Aber hier ist das Endresultat:
Code: Select all
class File {
__New( fileName ) {
if ( !fileExist( fileName ) )
Msgbox Datei existiert nicht : "%fileName%"
if ( inStr( fileExist( fileName ), "D" ) ) ;Wenn fileName auf einen Ordner oder ein Laufwerk verweist
Msgbox Datei ist keine valide Datei
Loop, Files, % fileName, F ;Da sich der Dateiname auf eine einzelne Datei bezieht, wird diese Schleife nur einmal ausgeführt.
this.name := A_LoopFileLongPath ;und hier wird er den Pfad auf den Wert setzen, den wir brauchen.
}
getPath() {
return this.name
}
getPathName() {
SplitPath, % this.name, fileName
return fileName
}
getPathDir() { ;same as getDirectory
return This.getPathDirectory()
}
getPathDirectory() {
SplitPath, % this.name, , fileDirectory
return fileDirectory
}
getPathExtension() {
SplitPath, % this.name , , , fileExtension
return fileExtension
}
getPathNameNoExtension() {
SplitPath, % this.name, , , , fileNameNoExtension
return fileNameNoExtension
}
getPathDrive() {
SplitPath, % this.name, , , , , fileDrive
return fileDrive
}
move( newFilePath, overwrite := 1 ) {
FileMove, % this.name, % newFilePath, % overwrite
}
copy( newFilePath, overwrite := 1 ) {
FileCopy, % this.name, % newFilePath, % overwrite
}
open( p* ) {
return FileOpen( this.name, p* )
}
getSize( unit := "" ) {
FileGetSize, fileSize, % this.name, % unit
return fileSize
}
getAttributes() { ;ein flag string siehe AutoHotkey Hilfe
return FileExist( this.name )
}
changeAttributes( changeAttributeString ) { ;siehe FileSetAttrib in der AutoHotkey hilfe für mehr infos
FileSetAttrib, % changeAttributeString, % this.name
}
getTimeAccessed() { ;in YYYYMMDDHH24MISS siehe AutoHotkey Hilfe für mehr Details
FileGetTime, timeCreated, % this.name, A
return timeCreated
}
setTimeAccessed( timeStamp ) {
FileSetTime, % timeStamp, % this.name, A
}
getTimeModified() {
FileGetTime, timeCreated, % this.name, M
return timeCreated
}
setTimeModified( timeStamp ) {
FileSetTime, % timeStamp, % this.name, M
}
getTimeCreated() {
FileGetTime, timeCreated, % this.name, C
return timeCreated
}
setTimeCreated( timeStamp ) {
FileSetTime, % timeStamp, % this.name, C
}
delete() {
FileDelete, % this.name
}
}
In diesem Teil des Tutorials haben wir gelernt:
- Was Objekte im Sinne von OOP sind
- Wofür Klassen in OOP verwendet werden
- Was ein Konstrukteur ist und wofür er gut ist
- Was Methoden und Attribute sind und wie man sie verwendet
- Was Getter und Setter sind
- Was Delegation ist und wofür sie gut ist
- unsere erste Klasse zu planen
- und sie zu codieren