home *** CD-ROM | disk | FTP | other *** search
-
- ;****************************************************************************
- ; Beispiel für die Benutzung der objektorientierten Assemblerprogrammierung.
- ;
- ; Diese Datei darf nur in Benutzung mit dem Optimierenden Makro-Assembler
- ; verwendet werden.
- ;****************************************************************************
-
- INCLUDE "exec/types.i"
- INCLUDE "macros.i"
- INCLUDE "OOMA.i"
-
-
- IMPORT InitObjectModule,RegisterClass,InitializeClasses
- IMPORT CreateObject
- IMPORT ClassObject
-
- ; Springe den Startcode an.
- jmp Start
-
-
-
-
-
-
-
-
-
-
- ;****************************************************************************
- ; Hier folgt die komplette Rechteck-Klasse. Sie erbt von Object.
-
-
- ; Erst einmal müssen die Instanzvariablen der Klasse Rechteck
- ; plaziert werden. Dies geschieht immer hinter den Variablen der
- ; Superklasse, in diesem Fall "Object". Hier wird also ein Objekt
- ; "Rechteck" definiert.
- STRUCTURE Rechteck,object_SIZEOF ; wir erben von Object
- UWORD rechteck_Höhe
- UWORD rechteck_Breite
- LABEL rechteck_SIZEOF ; Größe eines Rechtecks
-
- ; Definiere Methodennamen der Superklasse für unsere Klasse. Dies
- ; entlastet uns davon, sich daran erinnern zu müssen, in welcher
- ; Superklasse die Methode tatsächlich deklariert ist. Damit ist
- ; jede MethodenID mit dem Präfix "Rechteck_" ansprechbar. Jede
- ; MethodenID sollte mit dem Klassennamen als Präfix beginnen.
- SAMEMETHOD Rechteck_Initialize,Object_Initialize
- SAMEMETHOD Rechteck_Delete,Object_Delete
- ; Definiere neue Methoden, die es in der Superklasse noch nicht gab.
- ; Dies beginnt immer bei der Klassengröße der Superklasse.
- BEGINMETHOD Object_ClassSize
- DEFINEMETHOD Rechteck_SetzeHöhe
- DEFINEMETHOD Rechteck_SetzeBreite
- DEFINEMETHOD Rechteck_BerechneUmfang
- DEFINEMETHOD Rechteck_BerechneFläche
- ; Zum Abschluß muß immer die Klassengröße definiert werden. Sie gibt
- ; von Rechteck erbenden Klassen einen Aufsetzpunkt für neue Methoden.
- ; Wir selber haben dies oben per Object_ClassSize im Makroaufruf
- ; BEGINMETHOD ausgenutzt.
- ENDMETHOD Rechteck_ClassSize
-
-
-
- ; Jetzt kennen wir die Größe der Klassenstruktur (dies ist nämlich
- ; Rechteck_ClassSize) und können den Platz für die Klassenstruktur
- ; anlegen. Zweckmäßigerweise ist der in einem BSS-Hunk.
- ; Der Name einer Klasse sollte immer mit "Class" beginnen.
- BSS
- CNOP 0,4
- DEFINECLASS ClassRechteck,Rechteck_ClassSize
- CODE
-
-
-
- ; Melde die Rechteck-Klasse an.
- MeldeRechteckAn
- PROC d0-d1/a0-a2
- lea ClassRechteck,a0 ; Klassenzeiger
- lea ClassObject,a1 ; Superklasse
- lea .array,a2 ; InitArray
- moveq #rechteck_SIZEOF,d0 ; Objektgröße
- moveq #Rechteck_ClassSize,d1 ; Klassengröße
- jsr RegisterClass
- ENDPROC
-
- ; Dieses Feld legt fest, welche Methoden in der Klasse Rechteck
- ; selber vorhanden sind. Es wird immer mit dem ENDOVERWRITE-Makro
- ; abgeschlossen. Wird eine Methode der Klasse hier vergessen, dann
- ; ist entweder der Zeiger der Superklasse oder ein Nullzeiger in der
- ; Methodentabelle eingetragen. Dies führt dann beim Methodenaufruf zu
- ; einem Fehler.
- .array OVERWRITE Rechteck_Initialize
- OVERWRITE Rechteck_SetzeHöhe
- OVERWRITE Rechteck_SetzeBreite
- OVERWRITE Rechteck_BerechneUmfang
- OVERWRITE Rechteck_BerechneFläche
- ENDOVERWRITE ; Abschluß
-
-
-
- ; Dies ist die Methode zum Setzen der Höhe. Jede Methode wird mit
- ; dem Zeiger auf das Objekt in A5 aufgerufen, dieser heißt auch Self.
- ; Das Label dieser Methode hat zusätzlich das Präfix "m_". Daher
- ; lautet es hier "m_Rechteck_SetzeHöhe".
- ; Eingabe: A5: Self.
- ; D0: neue Höhe.
- METHODBODY Rechteck_SetzeHöhe
- PROC
- move d0,rechteck_Höhe(a5)
- ENDPROC
-
-
-
- ; Das gleiche noch einmal für die Breite.
- ; Eingabe: A5: Self.
- ; D0: neue Breite.
- METHODBODY Rechteck_SetzeBreite
- PROC
- move d0,rechteck_Breite(a5)
- ENDPROC
-
-
-
- ; Berechne den Umfang des Rechtecks.
- ; Eingabe: A5: Self.
- ; Ausgabe: D0: Umfang.
- METHODBODY Rechteck_BerechneUmfang
- PROC d1
- move rechteck_Höhe(a5),d1
- add d1,d1
- move rechteck_Breite(a5),d0
- add d0,d0
- add d1,d0 ; ergibt Umfang
- ENDPROC
-
-
-
- ; Berechne die Fläche des Rechtecks.
- ; Eingabe: A5: Self.
- ; Ausgabe: D0: Fläche.
- METHODBODY Rechteck_BerechneFläche
- PROC
- move rechteck_Höhe(a5),d0
- mulu rechteck_Breite(a5),d0 ; ergibt Fläche
- ENDPROC
-
-
-
- ; Diese Methode gibt es schon in der Superklasse Object. Sie sorgt
- ; hier noch für eine Standardeinstellung eines neuen Rechtecks.
- ; Eingabe: A5: Self.
- METHODBODY Rechteck_Initialize
- PROC
- SUPER a5,Rechteck_Initialize ; erst Superklasse aufrufen
- move #1,rechteck_Höhe(a5) ; jetzt Höhe auf 1
- move #1,rechteck_Breite(a5) ; und Breite auch
- ENDPROC
-
-
-
-
-
-
-
-
-
-
- ;****************************************************************************
- ; Hier folgt die komplette Quadrat-Klasse. Sie erbt von Rechteck. Der Quell-
- ; text hier ist einem Format gehalten, das wegen guter Lesbarkeit als Vorbild
- ; genommen werden sollte, Prozeduren und Methoden zu deklarieren und zu
- ; dokumentieren.
-
-
-
- ; Die Objektstruktur für Quadrate.
-
- STRUCTURE Quadrat,rechteck_SIZEOF ; wir erben von Rechteck
- LABEL quadrat_SIZEOF ; keine zusätzlichen Variablen nötig
-
- ; Quadrat_SetzeHöhe und Quadrat_SetzeBreite werden hier nicht definiert, da
- ; ein Quadrat nur eine Kantenlänge hat.
- SAMEMETHOD Quadrat_Initialize,Rechteck_Initialize
- SAMEMETHOD Quadrat_Delete,Rechteck_Delete
- SAMEMETHOD Quadrat_BerechneUmfang,Rechteck_BerechneUmfang
- SAMEMETHOD Quadrat_BerechneFläche,Rechteck_BerechneFläche
- BEGINMETHOD Rechteck_ClassSize
- DEFINEMETHOD Quadrat_SetzeKante ; neue Methode
- ENDMETHOD Quadrat_ClassSize ; Abschluß
-
-
-
- ; Die Quadrat-Klasse.
- BSS
- CNOP 0,4
- DEFINECLASS ClassQuadrat,Quadrat_ClassSize
- CODE
-
-
-
- ; Melde die Quadratklasse an.
-
- MeldeQuadratAn
- PROC d0-d1/a0-a2
- lea ClassQuadrat,a0 ; Klassenzeiger
- lea ClassRechteck,a1 ; Superklasse
- lea .array,a2 ; InitArray
- moveq #quadrat_SIZEOF,d0 ; Objektgröße
- moveq #Quadrat_ClassSize,d1 ; Klassengröße
- jsr RegisterClass
- ENDPROC
-
- .array OVERWRITE Quadrat_SetzeKante
- OVERWRITE Quadrat_BerechneUmfang
- ENDOVERWRITE ; Abschluß
-
-
-
- ;****************************************************************************
- ; Berechne den Umfang des Rechtecks. Diese Methode ist schneller als die der
- ; Rechteck-Klasse und ersetzt diese daher vollständig.
- ; Eingabe: A5: Self.
- ; Ausgabe: D0: Umfang.
-
- METHODBODY Quadrat_BerechneUmfang
- PROC
- move rechteck_Höhe(a5),d0 ; oder rechteck_Breite
- lsl #2,d0 ; * 4 ergibt Umfang
- ENDPROC
-
-
-
- ;****************************************************************************
- ; Setze Kantenlänge.
- ; Eingabe: A5: Self.
- ; D0: neue Länge.
- ; Ausgabe: Keine.
-
- METHODBODY Quadrat_SetzeKante
- PROC
- IFEQ 0
- ; Erste Implementierungsalternative.
- move d0,rechteck_Höhe(a5)
- move d0,rechteck_Breite(a5)
- ELSE
- ; Zweite Implementierungsalternative.
- METHOD a5,Quadrat_SetzeHöhe
- METHOD a5,Quadrat_SetzeBreite
- ENDC
- ENDPROC
-
-
-
-
-
-
-
-
-
-
- ;****************************************************************************
-
- Start
- PROC
- LOCAL einQuadrat,quadrat_SIZEOF ; Platz auf dem Stack
- SETLOC
-
- ; Zuerst muß das Objektmodul initialisiert werden.
- jsr InitObjectModule
-
- ; Melde alle Klassen an. Dabei ist die Reihenfolge völlig egal.
- ; Es ist wichtig, vor der Benutzung alle Klassen anzumelden und zu
- ; initialisieren.
- bsr MeldeQuadratAn
- bsr MeldeRechteckAn
-
- ; Nun müssen alle Klassen initialisiert werden. Wurde eine Klasse
- ; beim Anmelden vergessen, bekommen wir hier den Zeiger auf diese
- ; Klasse als Fehleranzeige zurück. Der Vererbungsbaum muß also
- ; zusammenhängen.
- jsr InitializeClasses
- tst.l d0
- bne .ende ; Fehler !!!
-
- ; Nun erzeugen wir ein Rechteck. Sein Speicher wird mit AllocMem
- ; belegt.
- lea ClassRechteck,a0
- jsr CreateObject
- move.l d0,d7
- beq .ende ; Fehler !!!
- ; Initialisiere das Rechteck.
- METHOD d7,Rechteck_Initialize
- ; Jetzt ist das Objekt gebrauchsfähig. Je nach Definition kann eine
- ; Initialize-Methode einer Klasse auch einen Erfolgswert o.ä. zurück-
- ; liefern.
-
- ; Jetzt einmal ein Objekt auf dem Stack. Es ist diesmal ein Quadrat.
- lea einQuadrat(SP),a4
- INITOBJECT a4,ClassQuadrat
- METHOD a4,Quadrat_Initialize
- ; Es wäre auch möglich, den Methodenaufruf wie folgt zu machen:
- ; METHOD einQuadrat(SP),Quadrat_Initialize
- ; Dies zeigt, daß eine beliebige Adressierungsart als Objektzeiger
- ; erlaubt ist.
-
- ; Setze die Breite des Rechtecks auf 2 und berechne den Umfang.
- ; Der Methodenaufruf landet bei SetzeBreite der Rechteck-Klasse bzw.
- ; bei BerechneUmfang der Rechteck-Klasse.
- moveq #2,d0
- METHOD d7,Rechteck_SetzeBreite
- METHOD d7,Rechteck_BerechneUmfang
- ; Ergebnis in D0.
-
- ; Setze die Kantenlänge des Quadrats auf 3 und berechne die Fläche.
- ; Der Methodenaufruf landet bei SetzeKante der Quadrat-Klasse bzw.
- ; bei BerechneFläche der Rechteck-Klasse, da die Quadrat-Klasse
- ; keine eigene Methode zur Flächenberechnung hat.
- moveq #3,d0
- METHOD a4,Quadrat_SetzeKante
- METHOD a4,Quadrat_BerechneFläche
- ; Ergebnis in D0.
-
- ; Das Rechteck muß noch wieder freigegeben werden. Wäre beim
- ; Initialisieren weiteres Belegen vorgekommen, dann müßte eine
- ; Methode "Rechteck_Cleanup" definiert sein, die nun hier vor dem
- ; Löschen aufgerufen würde.
- ; METHOD d7,Rechteck_Cleanup (entfällt hier)
- METHOD d7,Rechteck_Delete
- ; Das Quadrat hat Speicherplatz auf dem Stack, braucht also nicht
- ; freigegeben zu werden. Hätten wir für dieses Objekt Zusatzspeicher
- ; per AllocMem belegt und in einer Instanzvariablen vermerkt, müßte
- ; wie oben gesagt noch eine Aufräummethode "Quadrat_Cleanup" aufgerufen
- ; werden.
-
- ; Ende des Tests.
- .ende moveq #0,d0
- ENDPROC
-
-
-
-
-
-
-
-
-
-
- END
-
-