Zitat aus den RKMs :
"Boopsi is an acronym for Basic Object Oriented Programming System for Intuition. Using the Object Oriented Programming (OOP) model, Boopsi represents certain Intuition entities, like "Gadgets" and "Images" , as objects."
Wie man deutlich lesen kann, handelt es sich bei BOOPSI um Objekte für die Amiga Intuition-Library. BOOPSI ist damit ganz klar nur eine Unterklasse im OOP4A System. Das gleiche Schicksal trifft übrigens auch MUI :-)) bzw. jede andere Gui-Library.
OOP4A hat 1. als Ziel Programmiersprachen die keinen direkten OOP Support haben mit eben diesem auszurüsten. 2. ein offenes System für Programmierer zu haben, das sich nur mit einigen Wrapperklassen an ein neues Betriebsystem oder neue CPU anpassen läßt. 3. etwas mehr Sicherheit bietet im Umgang mit Aufrüfen von Funktionen.
1. | Dieses Ziel hat OOP4A schon mit der ersten Release erreicht gehabt. |
2. | Da jeder an diesem freien Projekt mitarbeiten kann und es eine offene Architektur hat, die ohne zusätzliche Informationen wie FD, LVO, LIB Files auskommt, ist es leicht portierbar. |
3. |
OOP4A ist Aufrufsicher , das bedeutet , daß man mit einem Methodenaufruf
einer Methode, die nicht in der Klasse vorhanden ist, weil z.B. eine
alte Version benutzt wird, das System nicht zum Absturz bringen kann.
Das normale Librarysystem vom Amiga geht davon aus, daß ein Compiler
weiß, was in der Library enthalten ist und nur solchen Code erzeugt, der
auch ausführbar ist ohne das System zugefährden. In der Praxis bedeutet
das aber, daß neuere Programme , ohne zu prüfen ob die neuere Lib auch vorliegt,
alte Libs mit neuen Funktionen aufrufen können, was nicht selten mit einem Absturz
endet. OOP4A hat dem einen Riegel vorgeschoben, in dem alle Methoden in der Klasse mit Namen gespeichert sind und beim Aufruf der Methode lexikalisch verglichen werden. Damit kann eine Klasse auch die Reihenfolge der Methoden in der Klasse ändern ohne das andere Klassen dies überhaupt bemerken würden. Programme können allerdings immernoch abstürzen, wenn der Programmierer der Klasse oder aufrufenden Programm schlecht programmiert haben. Die Verantwortlichkeit für Plausibilitätsprüfungen liegen allerdings nun ganz klar bei der Klasse selbst. Da aber nur noch KlassenObjekte benutzt werden und diese einheitliche Zugriffmechanismen haben, minimiert sich die Fehlerhäufigkeit schon beträchtlich. Anhand der string.class und der mem.class zeigt sich das ganz deutlich.
Interface von mem.class und string.class Betrachten wir mal den Konstruktor der Klasse String.class:
public Constructor() { speicher.getMem(0) speicher.clearMem() } Als Vorwort sein noch erwähnt, daß Objekte die mit Klassennamen global erzeugt wurden, automatisch vom Konstruktor erzeugt werden, bevor irgendjemand sie benutzen kann. Eigentlich sieht der Konstruktor nach dem "Vorbehandeln" mit PreassXX so aus:
public Constructor() { exec=new("com/amiga/system/execwrapper",0) tools=new("system/misc",0) speicher=new("system/mem",0) if exec&tools&speicher=0 { del(exec) del(tools) del(speicher) return -1 } speicher.getMem(0) speicher.clearMem() } Im Konstruktor wird also für jeden String schonmal ein MemoryObjekt mit einer Speicherlänge von NULL erzeugt. Und dessen Speicher gelöscht. Bei NULL Byte Speicher im MemoryObjekt ist das zwar nicht sinnvoll , weil nichts passiert, aber eine zukünftige string.class könnte dort schon 30 Bytes für einen String reservieren, um so nicht immer neuen Speicher anfordern zumüssen, wenn der String mal länger wird, und dann sollte dort ein ClearMem() durchgeführt werden.
public addString(long pointer) { long size res size=tools.strlen(long pointer) res=speicher.addMemContent(pointer,size) return res } public addStringObject(String myString) { long size pointer res Object myString size=myString.getSize() pointer=myString.getAddr() res=speicher.addMemContent(long pointer,long size) return res } Die string.class kann echte Nullterminierte Strings oder StringObjekte zusammenfügen. Dazu wird die Adresse und die Länge des Strings an das MemoryObjekt weitergereicht, das dann letztendlich das anfügen durchführt:
public addMemContent(long source,long sourcelen) { long mem2 len2 len2==memsize+sourcelen mem2=exec.AllocMem(len2,#MEMF_FAST!MEMF_CLEAR) if mem2#0 { exec.CopyMem(mem_p,mem2,memsize) exec.FreeMem(mem_p,memsize) exec.CopyMem(source,mem2+memsize,sourcelen) mem_p==mem2 memsize==len2 return memsize } return 0 }
Ganz einfach, das Stichwort heißt » Verantwortlichkeit « . Die MemoryKlasse kennt alle Zusammenhänge die Speicherverwaltung betreffen. Die Stringklasse kennt alles was mit Strings und deren Eigenschaften zutun hat. Daher gibt es eine Aufgabenteilung , die Stringklasse übernimmt alle Anfragen die mit Strings zutun haben und verarbeitet diese, wenn etwas am Speicher verändert werden soll, dann übergibt Sie die Aufgabe an das MemoryObjekt. Sie muß nicht mehr wissen wo der Speicherbereich des Strings liegt oder wie lang der String ist, das ist Aufgabe des MemoryObjekts. Dem MemoryObjekt wiederum ist es egal was es da verwaltet, es kümmert sich nur um den Speicher und dessen Verwaltung. Damit kann die Klasse mem von jeder anderen Klasse als das benutzt werden was sie ist, ein SpeicherverwaltungsObjekt. Diese Verantwortlichkeit zieht sich durch die ganze OOP und ist nicht auf OOP4A beschränkt. Wer jetzt immernoch der Meinung ist, das BOOPSI = OOP4A ist, der sollte sich dringend mal ein OOP Buch besorgen. |