Smalltalk


Das Arbeiten mit Smalltalk

Smalltalk besteht aus vier Teilen:
  1. der virtuellen Maschine (oe20),
  2. dem Image(<name>.im),
  3. der Changes Datei (<name>.cha)und
  4. der Source Datei (visual.sou)
In der Regel hat jeder Smalltalkbenutzer ein eigenes Image (Speicherabzug der virtuellen Maschine) und eine eigene Changes Datei. Dieses wird mit dem File-Save As Menüpunkt im Launcher erstellt. Jedes Image ist ungefähr 4,5 MB groß und wächst, je mehr man programmiert.

In dem Changes File werden die Veränderungen, die man an dem Image vornimmt, protokolliert und außerdem enthält es den Sourcecode der vom Benutzer definierten Klassen. (Das Image enthält nur die übersetzten Klassen.) Das Changes File wird automatisch in dem Verzeichnis generiert von dem Smalltalk gestartet wurde. Deswegen sollten von einem Verzeichnis aus nicht mehrere Smalltalkprozesse gestartet werden, da sonst die Changes Dateien durcheinander kommen.

Die Source Datei braucht nur einmal für jede Installation vohanden zu sein und enthält den Sourcecode der Systemklassen.


Starten von Smalltalk

Für die Übungen verwenden wir VisualWorks 2.0 von ParcPlace Systems.

Smalltalk wird mit

/home/stud/hubert/vw/bin/vw /home/stud/hubert/vw/image/visual.im
gestartet, falls noch keine eigene Image Datei existiert, ansonsten mit
/home/stud/hubert/vw/bin/vw <name>.im
Es erscheinen zwei Fenster. Das Fenster, das mit VisualWorks bezeichnet ist, heißt Launcher. Vom Launcher aus werden die Werkzeuge zum Programmieren, Texte edieren usw. gestartet.

Smalltalk bietet eine Online-Dokumentation an; sie ist vom Launcher über das Help Menü erreichbar. Für den Anfang besonders interssant sind das VisualWorks Cookbook und dort das erste Kapitel.

Innerhalb des von Smalltalk kontrollierten Bereichs der Fenster habe die Maustasten folgende Bedeutung:


Programmieren in Smalltalk


Der System Browser

Mit Hilfe des System Browsers (Menü Browse-All Classes im Launcher) kann man neue Klassen und Methoden definieren.

Der System Browser besteht aus fünf Teilfenstern und zwei Knöpfen. Die vier oberen Fenster enthalten Listen und das untere Fenster Text. Jedes Teilfenster hat ein eigenes Menü beim betätigen der mittleren Maustaste. Die Bedeutung des Textes im Textfenster ist abhängig davon welche Selektion in den Listen gemacht wurde. In der Regel erscheinen im Textfenster die entsprechenden Definitionen der Klassen oder Methoden, zum Beispiel:

Object subclass: #Person
	instanceVariableNames: 'name vorname '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Example'
oder Beispiele für Definition, die, wenn vom Benutzer korrekt ausgefüllt und akzeptiert (mittlere Maustaste accept) vom System übernommen werden.
NameOfSuperclass subclass: #NameOfClass
	instanceVariableNames: 'instVarName1 instVarName2'
	classVariableNames: 'ClassVarName1 ClassVarName2'
	poolDictionaries: ''
	category: 'Example'

Die Liste im äußerst linken Fenster enthält die Liste der Klassenkategorien. Die Liste rechts daneben enthält die Klassendefinition, die in der selektierten Kategorie zusammengefaßt sind. Die nächste Liste enthält die Liste von Methodenkategorien, die zu der selektierten Klasse gehören. Die Liste im äußerst rechten Fenster enthält die Methoden, die in der selektierten Methodenkategorie zusammengefaßt sind.

Neue Klassen

Klassen werden mit dem System Browser definiert. Zuerst wird eine Klassenkategorie erzeugt bzw. selektiert in der man die Klassedefinition ablegen will. Neue Klassen werden definiert indem man etwaige selektierte Klassen deselektiert und folgendes Template ausfüllt:
NameOfSuperclass subclass: #NameOfClass
	instanceVariableNames: 'instVarName1 instVarName2'
	classVariableNames: 'ClassVarName1 ClassVarName2'
	poolDictionaries: ''
	category: 'Tools-Programming'
NameOfSuperclass wird durch die Klasse ersetzt von der die neue Klasse erben soll (diese Klasse muß im System schon vorhanden sein und kann z.B. die Klasse Object sein). NameOfClass wird durch den Namen der Klasse ersetzt, die man erzeugen will usw. Anschlie"send wird der Text akzeptiert (mittlere Maustaste accept).

Beispiel:

Object subclass: #Person
	instanceVariableNames: 'name vorname alter'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Example'

Klassen sollten einen Klassenkommentar erhalten.

Wenn in den Übungsaufgaben nicht ausdrücklich gefordert, sollte man keine Systemklassen ändern.

Neue Klassenkategorien

Klassenkategorien dienen dazu zusammengehörige Klassen unter einem Namen zusammenzufassen damit man sie leichter findet. Die Liste am linken Rand im System Browser enthält die Liste der im System vorhandenen Kategorien.

Neue Kategorien werden mit dem Menüpunkt add ... (mittlere Maustaste in der Liste der Kategorien) erzeugt.

Kommentieren von Klassen

Klassen sollten in der Regel Klassenkommentare enthalten, die den Zweck einer Klasse beschreiben. Klassenkommentare werden erzeugt indem man im System Browser die Klasse selektiert und im Menü zu dem Klassenfenster comment auswählt. Anschlie"send kann man im Textfenster den Kommentar eingeben und akzeptieren (mittlere Maustaste accept).

Neue Methoden

Im System Browser werden neue Methoden für eine Klasse erzeugt, indem man zuerst die entsprechende Methodenkategorie ezeugt bzw. selektiert in der die Methode enthalten sein soll. Anschließend wird im Textfenster das Template
message selector and argument names
	"comment stating purpose of message"

| temporary variable names | statements

ausgefüllt und durch akzeptieren (im Textfenster mittlere Maustaste accept) übersetzt.

Ein Beispiel für eine Methode der Klasse Person:

printOn: aStream 
   "Fuege einen String an den Strom aStream an, der mich selbst 
   beschreibt"

name isNil ifFalse: [aStream nextPutAll: name]. vorname isNil ifFalse: [name isNil ifFalse: [aStream nextPutAll: ', ']. aStream nextPutAll: vorname]. aStream nextPutAll: ' ('; print: alter; nextPut: $)

Neue Methodenkategorien

Die Methodenkategorien dienen dazu zusammengehörige Methoden einer Klasse zusammenzufassen. Neue Methodenkategorien werden mit dem Menüpunkt add ... (mittlere Maustaste in der Liste der Methodenkategorien) erzeugt.

Testen von Klassen und Methoden

Zum einfachen Testen seiner Klassen kann man die Workspace nehmen (im Launcher Tools-Workspace). Um Eingaben vom Benutzer zu erhalten kann man DialogView request: <string> verwenden und zur Ausgabe Transcript nextPutAll: <string>; cr; endEntry.

Beispiel:

| p name vorname jahr |
name := DialogView request: 'Name'.
vorname := DialogView request: 'Vorname'.
jahr := Integer readFromString: (DialogView request: 'Geburtsjahr').
p := Person new.
p name: name.
p vorname: vorname.
p geburtsjahr: jahr.
Transcript nextPutAll: p name, ', ',p vorname,' alter: ', p alter printString; cr; endEntry.

Anschließend selektiert man den ganzen Text und führt ihn mittels do it vom Menü der mittleren Maustaste aus.

Die Auswertung eines Ausdrucks liefert ein Objekt zurück. Bei do it wird dieses Objekt ignoriert, bei print it wird seine Darstellung als String (durch die Methode printOn: definiert) am Ende der Selektion in den Text eingefügt und bei inspect it wird ein Werkzeug aktiviert, mit dem man das Ergebnisobjekt inspizieren kann (Inspector).

Sichern nach getaner Arbeit

Seine aktuelle Arbeit sichert man indem man im Launcher den Menüpunkt Changes-File Out Changes... verwendet. Es werden dann alle Klassen und Methodendefinition, die man seit dem Starten des Images bzw. seit dem man das letzte Mal Changes-Empty Changes... ausgeführt hat, in eine Datei geschrieben. Hat man nur Änderungen in einer Klassenkategorie vorgenommen, dann kann man auch file out... in dem Menü des Fensters für die Klassenkategorien im System Browsers verwenden.

Abgabe der Übungen

Für die Abgabe muß dann noch mit einen Texteditor (z.B. im Launcher Tools-File List) der Kommentar "Susi Sinnlos, Rudi Ratlos"! eingefügt werden (s.a. Übungsblätter). Beachte die geänderten Kommentarklammern " ". Außerdem gehört der Inhalt der Workspace und ein Probelauf als Kommentar in die Abgabe.

Beispiel für eine Abgabe:

"Susi Sinnlos, Rudi Ratlos"!

"| p name vorname jahr | name := DialogView request: 'Name'. vorname := DialogView request: 'Vorname'. jahr := Integer readFromString: (DialogView request: 'Geburtsjahr'). p := Person new. p name: name. p vorname: vorname. p geburtsjahr: jahr. Transcript nextPutAll: p name, ', ',p vorname,' alter: ', p alter printString; cr; endEntry.

Ausgabe auf SystemTranscript bei der Eingabe 'Baumeister', 'Hubert' und 1963:

Baumeister, Hubert alter: 32 "!

'From VisualWorks(R) Release 2.0 of 4 August 1994 on 11 January 1995 at 3:24:22 am'!

Object subclass: #Person instanceVariableNames: 'name vorname alter ' classVariableNames: '' poolDictionaries: '' category: 'Demo'!

!Person methodsFor: 'accessing'!

alter ^alter!

alter: i alter := i!

geburtsjahr ^Date today year - alter!

geburtsjahr: i alter := Date today year - i!

name ^name!

name: aString name := aString!

vorname ^vorname!

vorname: aString vorname := aString! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

Das Laden von Klassen

Einmal gesicherte Klassen können wie folgt wieder in Smalltalk eingelesen werden.

Zuerst wird ein File Editor auf die Datei geöffnet in die vorher die Klassen geschrieben wurden (Launcher Tools-File Editor). Danach wird der ganze Text selektiert; am einfachsten geht das mit einem Doppelklick am Anfang der Datei. Anschließend wird file it in im Menü der mittleren Maustaste ausgewählt.


Part of Objektorientierte Programmierung
Harald Ganzinger, Peter Barth, Hubert Baumeister
September 6, 1996

Imprint | Data Protection