Self [] ist eine Programmiersprache, die vor allem in Hinblick auf Ausdrucksfähigkeit und Formbarkeit hin von Randall B. Smith und David Ungar entworfen wurde. Um diese Ziele zu erreichen, wurde ein rein prototypenbasiertes Objektmodell mit einheitlichem Zugriff auf Zustand und Verhalten der Objekte, also auf ihre Attribute und Methoden, entwickelt. Im Gegensatz zu anderen Programmiersprachen ist es in Self möglich, den Zustand von Objekten zu vererben und die Vererbung zur Laufzeit dynamisch anzupassen.

Die letzte von Sun herausgegebene Version 4.3 wurde im Juni 2006 veröffentlicht. Sie läuft auf Intel- und PowerPC-basierten Apple-Rechnern und auf Sun SPARC, aber nicht unter Linux oder Microsoft Windows. bei sun.com Die Weiterentwicklung wird danach nicht mehr durch Sun betrieben und geschieht derzeit unabhängig.

Ideen und Konzepte, die ihren originären Ursprung in der Programmiersprache Self haben, wurden über die Jahre sowohl in das Squeak Smalltalk-System übernommen, als auch in Programmiersprachen wie Slate oder io weitergeführt.

mini|Das Self-Universum

Die herausragende Self-Eigenschaft ist wohl das Self-Universum, eine Art grafische Benutzeroberfläche (GUI), innerhalb derer mit dem Self-Laufzeitsystem interagiert werden kann. Eine Interaktion erfolgt hierbei in der Regel über die Maus und/oder die Tastatur. Visualisiert wird das Self-Universum mittels des GUI-Frameworks Morphic. Betritt eine Person das Self-Universum, so geschieht dies immer über die Lobby, eine Anspielung auf die Empfangshalle eines Hotels. In ihr befinden sich alle im System vorhandenen Objekte, Module, Namensräume und Traits. Das Konzept des (Programmier-)Universums als auch das Morphic-Konzept wurde nahezu identisch im Squeak Smalltalk-System umgesetzt.

Trotz der diversen Portierungen sollte man bedenken, dass es sich bei der Programmiersprache Self um ein eher akademisch motiviertes Unterfangen handelt. Trotzdem hatte und haben die in Self erprobten Neuheiten Einfluss auf neuere objektorientierte Programmiersprachen.

Geschichte Self wurde ursprünglich 1986 von David Ungar und Randall B. Smith während ihrer Arbeit am Xerox-Parc-Institut entworfen. Ihr Ziel war es, nachdem Smalltalk-80 veröffentlicht worden war, die Software-Technologie weiter voranzubringen. Sie wechselten zur Stanford-Universität und veröffentlichten im Folgejahr den ersten funktionierenden Compiler. Das erste vollständige Self-System wurde 1990 veröffentlicht; im Jahr darauf wechselte die Gruppe zu Sun Microsystems, wo das Self-System als Experimentierfeld für die Entwicklung genutzt wurde. Hier kam Urs Hölzle dazu, der neue Compiler- und VM-Techniken entwickelte und an der Entwicklung der Programmiersprache Strongtalk beteiligt war. 1995 wurde die Entwicklung bei Sun Microsystems offiziell eingestellt: „Self 4.0 ist, in einem gewissen Sinn, der Gipfelpunkt des Self-Projekts, das aber bei Sun offiziell nicht weitergeführt wird.“ bei sun.com Allerdings gab es noch die Entwicklergruppe an der Stanford-Universität sowie verschiedene andere Initiativen. Trotz des offiziellen Stops wurde im September 2002 die Version 4.1.6 veröffentlicht. bei sun.com Im April 2004 erschien dann die Version 4.2 und im Juni 2006 die Version 4.3. Seit Juli 2010 gibt es eine Version 4.4.Version 4.4 Im Februar 2011 wurde ein experimenteller Snapshot einer Version 4.5 herausgegeben.Version 4.5 (früher Snapshot) auf blog.selflanguage.org Bis zur Veröffentlichung einer fertigen Version unter dem Namen "Mallard" dauerte es jedoch bis Januar 2014. auf blog.selflanguage.org Eine weitere Version mit dem Namen "Mandarin" entstand 2017.

Die Entwicklungsumgebung Das Self-System kann als prototypenbasierte Smalltalk-Variante verstanden werden. Die Entwickler bezeichnen die Sprache als Smalltalk-Dialekt und meinen damit, dass sich die Syntax der Sprache und auch die Objektbibliothek weitgehend an Smalltalk orientiert. Der Klassenbrowser von Smalltalk wurde durch einen Objektbrowser ersetzt.

Wie Smalltalk beruht Self auf einer Laufzeitumgebung und einer virtuellen Maschine. Self-Programme benötigen, genau wie andere auf virtuelle Maschinen beruhende Systeme, immer die zugehörige Speicherumgebung, um ausgeführt werden zu können. Als Folge werden Anwendungen häufig als Abbild des Speichers ausgeliefert. Dieses Speicherabbild wird auch Snapshot genannt.

Eine Alternative zur Auslieferung von Snapshots sind Textdateien, in die Änderungen am System oder auch ganze Module über den sogenannten Transporter ex- und importiert werden können. Diese Textdateien lassen sich mit einem beliebigen Editor bearbeiten. Sie sind vergleichbar mit einem C-Quelltext, jedoch wesentlich mächtiger. Das gesamte System lässt sich damit steuern. Da diese Textdateien auch automatisch mit dem Start des Systems eingelesen werden können, kann Self genau wie Perl als Skriptsprache genutzt werden.

Die typische Größe eines Snapshots ist ca. 13 MB für ein vollständiges System mit JIT-Compiler, Interpreter und der Entwicklungsumgebung. Der von Smalltalk geerbte Vorteil ist, dass die Arbeit am System jederzeit, auch mitten in einer Berechnung, unterbrochen werden und in Snapshots gespeichert werden kann. Alle Änderungen, also das was bei klassischen Systemen dem Programmieren, einer Zeichnung oder irgendeiner Arbeit mit dem System entspricht, können beim nächsten Neustart auf Wunsch wieder vorhanden sein. Das System wacht da auf, wo es verlassen wurde. Self ist persistent.

Die Self-Entwicklungsumgebung ermöglicht es Quellcode, Objekte, Vererbung, die Objekthierarchie oder einzelne Werte zur Laufzeit zu verändern. Möglich wird das durch die Fähigkeit zum Multitasking und einen nahtlos in das System integrierten Debugger. Das führt zu einer inkrementellen Art des „on the fly“-Entwickelns. Einige moderne Methoden der Softwareentwicklung, etwa die Agile Softwareentwicklung oder das Adaptive Software Development, propagieren Ähnliches.

So ist die Entwicklungsumgebung auf das schnelle und kontinuierliche Ändern einzelner Objekte zugeschnitten. Das Refactoring des „Objekt“-Designs ist beinahe so einfach wie das Entfernen einer Methode via Drag & Drop, um sie so einem neuen Objekt zuordnen zu können. Einfachere Aufgaben wie das Erstellen von Test-Methoden können durch eine Kopie bewältigt werden. Die entsprechende Methode wird anschließend in die Objekt-Kopie gezogen, um sie so verändern zu können. Im Vergleich zu traditionellen Systemen besitzt nur das soeben neu erzeugte Objekt auch neuen Quellcode. Es ist folglich nicht erforderlich, Code neu zu kompilieren, um ihn testen zu können. Sobald sichergestellt wurde, dass die Test-Methode entsprechend der Spezifikation funktioniert, kann diese zurück in das Ausgangs-Objekt kopiert werden.

Sprachbeschreibung Im Folgenden soll nur ein erster Eindruck dieser Programmiersprache vermittelt werden. Für umfassende Informationen sei auf The Self Language auf research.sun.com und Teaching Self and Prototype-Based Programming auf research.sun.com verwiesen.

Self ist eine objektorientierte, prototypenbasierte Programmiersprache. Die Grundlage bilden einige wenige einfache Konstrukte: Prototypen, Steckplätze und das Verhalten. Im Gegensatz zu den Konzepten von Smalltalk und vielen anderen Programmiersprachen gibt es weder Klassen noch Variablen. Das Programmiermodell beruht im Wesentlichen auf kommunizierenden Objekten und einer einfachen Form von Vererbung.

In Self werden keine Programme im eigentlichen Sinn geschrieben – stattdessen wird das „Self-Universum“ beschrieben. Hier gibt es nur Objekte, die durch das Verschicken von Nachrichten miteinander kommunizieren. Dieses Verschicken einer Nachricht entspricht einem Prozedur-Aufruf in der klassischen Programmierung. Neue Objekte werden durch Klonen bestehender Objekte erzeugt.

Durch das Prototypen-Konzept ist eine interaktive Programmierung möglich: Der Programmierer interagiert mit den Objekten im Self-Universum.

In Self wird nicht zwischen dem Zustand eines Objekts und seinem Verhalten unterschieden. Der Zustand eines Objekts ergibt sich aus seinen Eigenschaften, also den Werten seiner Attribute. Das Verhalten eines Objekts wird in seinen Methoden beschrieben. Dadurch, dass es keinen Unterschied zwischen dem Zustand und dem Verhalten gibt, wird die Lücke verringert, die in anderen Programmiersprachen zwischen Objekten, Prozeduren und Variablen besteht. In Self ist alles eins.

So liefert beispielsweise der Aufruf einer Eigenschaft – sofern das Objekt oder eines seiner Vorfahren diese Eigenschaft denn hat – deren Wert: aPerson name

In dieser Anweisung wird die Eigenschaft name des Objekts aPerson aufgerufen bzw. abgefragt. Mit der folgenden Anweisung wird derselben Eigenschaft ein Wert zugewiesen: aPerson name:'myself'

Sprachkonstrukte Objekte bestehen aus (theoretisch) beliebig vielen Steckplätzen (slots). Ein Steckplatz hat einen Namen und kann ein Attribut (Wert) oder eine Methode (Prozedur) enthalten. In jedem Fall ist es ein Objekt, das er aufnimmt. Ein Objekt besteht somit aus einem oder mehreren Steckplätzen für Objekte, auf die mittels des Namens zugegriffen werden kann.

Ein Methoden-Objekt enthält eine oder mehrere Anweisungen, die ausgeführt werden, wenn das Methoden-Objekt aufgerufen wird. Ein Attribut-Objekt liefert sich selbst zurück, wenn es wie ein Methoden-Objekt aufgerufen wird.

Neue Objekte werden durch Klonen erzeugt. Dazu wird ein passendes Objekt als Prototyp benutzt, also sozusagen als eine Kopiervorlage. Jedes Objekt kann als Prototyp genutzt werden.

Ein kurzes Programm Hier das klassische Hallo-Welt-Programm: 'Hello, World!' print.

Der Punkt am Ende der Anweisung bewirkt, dass die Rückgabe des Wertes – die eigentlich bei allen Nachrichten erfolgt – unterdrückt bzw. vermieden wird. Hier noch einmal in einer aufwändigeren Form: (desktop activeWindow) draw: (labelWidget copy label: 'Hello, World!').

Erläuterung: Als erstes wird das desktop-Objekt nach dem aktiven Fenster gefragt. Das desktop-Objekt sieht dazu in seiner Liste der aktuellen Fenster nach und liefert das entsprechende Objekt zurück. Diesem Objekt wird in dem Steckplatz namens draw eine zuvor erzeugte Kopie des labelWidget-Objekt eingetragen. Bevor das passiert, wurde der labelWidget-Kopie bereits die Nachricht geschickt, dass es einen Steckplatz mit dem Namen label anlegen soll und dort den Wert Hello, World! ablegen soll.

Vererbung Theoretisch ist jedes Self-Objekt eine eigenständige Entität. Es existieren keine Klassen, keine Meta-Klassen etc., um die Eigenschaften und Verhaltensweisen eines Objektes zu spezifizieren. Änderungen am Objekt selbst beeinflussen das Verhalten anderer Objekte nicht. In Einzelfällen jedoch wäre dies durchaus sinnvoll. Grundsätzlich versteht ein Objekt nur die Nachrichten, die auch einem seiner Slots eindeutig zugeordnet werden können. Verweisen jedoch ein oder mehrere Slots auf ein parent-Objekt, so ist das Objekt imstande, Nachrichten an diese Elternobjekte zu delegieren, insofern es diese selbst nicht zu interpretieren vermag. Auf diesem Weg verwaltet Self Aufgaben, die in traditionellen objektorientierten Sprachen das Vehikel der Vererbung benötigt hätten. Diese Verfahrensweise wird zudem benutzt, um Namensräume zu implementieren.

Um den Zusammenhang der Vererbung besser veranschaulichen zu können, soll an dieser Stelle von einem Objekt namens BankKonto ausgegangen werden. Dieses soll in einer einfachen Buchhaltungsanwendung zum Einsatz kommen. Es liegt nahe, das Objekt BankKonto mit den Methoden einzahlen und abheben auszustatten. Zusätzliche Slots für einfache Daten werden ebenfalls benötigt. Das soeben spezifizierte Objekt ist ein Prototyp, stellt aber bereits ein voll funktionsfähiges Bankkonto dar.