Einführung in Apples neue Programmiersprache Swift, Teil 1

Seite 2: Spielplatz und die Typen

Inhaltsverzeichnis

Eine REPL-Umgebung (Read Eval Print Loop) soll dem Entwickler ein wenig Skriptsprachen-Feeling à la Ruby vermitteln und eignet sich sowohl für das Erlernen von Swift als auch zum Testen des eigenen Codes. Der Name der REPL-Umgebung in der Entwicklungsumgebung von Xcode 6 lautet "Spielplatz" – im Englischen "Playground". Anleihen von der Eclipse-Umgebung für Scala sind nicht zu übersehen.

Detaillierte Informationen über den Playground finden sich auf Apples Entwickler-Seiten. Die "Spielwiese" benötigt als Grundlage OS X 10.9.3 (Mavericks) oder höher. Das Beispiel in Abbildung 1 zeigt, dass die REPL-Umgebung Anweisungen unmittelbar ausführt und das Ergebnis auf der rechten Fensterseite ausgibt. Übrigens auch dann, wenn das Ergebnis eine bewegte oder unbewegte Grafik ist.

Der Swift Playground lädt Entwickler zum Experimentieren und Testen ein (Abb. 1).

(Bild: Apple)

Eine besondere Zugabe des Playgrounds ist, die Veränderung der Werte von Ausdrücken mit einer Grafik zu analysieren. Gerade für komplexere Anweisungssequenzen erweist sich diese intuitive Analysemöglichkeit als vorteilhaft. Der besseren Verständlichkeit halber ist das folgende Beispiel in Abbildung 2 einfach gehalten.

Der Swift Playground lädt Entwickler zum Experimentieren und Testen ein (Abb. 2).

(Bild: Apple)

Der Playground ist auch ein guter Anlaufpunkt, um die Sprache näher kennen zu lernen. Swift bietet gegenüber Objective-C eine ganze Reihe zeitgemäßer Sprachmerkmale, mit denen es sich im Playground experimentieren lässt. So ist Swift einerseits typsicher, kann aber wie Vetter C# Datentypen durch Typinferenz ermitteln. Sogar Funktionen bilden Datentypen, ganz wie in Scala. Die Sprache bietet aber noch viel mehr.

Wer aus der Welt von C/C++ oder Objective-C kommt, kann sich zunächst gar nicht vorstellen, dass es auch ohne Header-Dateien geht. Für Fremdgänger mit Java-, C#- oder Scala-Hintergrund ist das dagegen selbstverständlich. Ein import-Statement erlaubt das Nutzen von Modulen. Und das ohne explizite Angabe von Pfaden und unabhängig von der Implementierungssprache der Bibliothek. Etwa beim wichtigen Beispiel Cocoa:

import cocoa

Scala- und C#-Programmierer dürften sich dank Déjà-vu die Augen reiben, wenn sie Variablen- und Konstantendefinitionen in Swift unter die Lupe nehmen – es gibt fast keine Unterschiede, außer dass es in Scala nicht let, sondern val heißt. Definieren können Entwickler Konstanten und Variablen wie folgt:

let magazin : String = "iX"     // Konstantendefinition
var searchPattern : String = "" // Variablendefinition und Initialisierung

Dabei sind Konstantenvereinbarungen am Schlüsselwort let zu erkennen, Variablenvereinbarungen an var. Im Gegensatz zu Konstanten ist es bei Variablen nicht notwendig, die Initialisierung an der Definitionsstelle vorzunehmen. Erfolgt allerdings überhaupt keine Initialisierung einer Variablen in einem Programmpfad, quittiert der Compiler jedes versuchte Lesen derselben mit einer Fehlermeldung.

Wie erwähnt, bedarf es meistens keiner expliziten Typangabe. Die Datentypen kann der Compiler im Regelfall, aber nicht immer mit Typinferenz selbst herleiten. Bei Variablenzuweisungen geschieht das durch Ermitteln des Datentyps der rechten Zuweisungsseite. Deshalb ist im Beispiel auch eine kürzere Schreibweise möglich:

let magazin = "iX"
var searchPattern = ""

Bei den Bezeichnern sind alle Unicode-Zeichen zugelassen, egal ob Buchstaben, Zahlen oder Grafiksymbole, sodass auch Folgendes machbar ist.

let π=3.141

Wer will, kann den eigenen Code unleserlich gestalten. Darum verbietet sich das übermäßige Einbauen von Sonderzeichen.

Die Initialisierung der Konstanten z (s. u.) darf durch beliebige Ausdrücke erfolgen, muss also auf der rechten Seite der Zuweisung nicht unbedingt allein auf Konstanten zurückgreifen:

let x = "47"
let y = "11"
let z = "\(x) + \(y) = \(x + y)" // berechnete Zeichenkette

Mit der Notation \(x) lässt sich der Wert von x in Zeichenketten integrieren, was unter anderem für Bildschirmausgaben und Logging handlich ist. Wenn in die Zeichenkette Größen aus variablen Ausdrücken einfließen sollen, kann der Compiler die vollständige Zeichenkette nicht während der Übersetzungszeit zusammenfügen wie bei einer Beschränkung auf Konstanten und einfache Operationen. Eine auch aus variablen Ausdrücken zusammengesetzte Zeichenkette ist erst zur Laufzeit berechenbar. Sprachdesigner bezeichnen den dynamischen Einbau von Daten in eine Zeichenkette als "String Interpolation".

Swift unterscheidet – wie Scala – zwischen Wert- und Referenztypen, von denen erstere über den Stack und letztere über den Heap verwaltet werden. Die Übergabe eines Werts erfordert daher das Kopieren seiner Bestandteile, während bei Referenztypen, nomen est omen, nur eine Kopie der Referenz erfolgt; das Objekt selbst verweilt auf seiner angestammten Position im Heap – bis es keiner mehr referenziert. Das heißt, die Änderung eines referenzierten Objekts kann von überall dort erfolgen, wo die Referenz bekannt ist, was in der Praxis durchaus unliebsame Überraschungen verursachen kann. Aggregierende Werttypen enthalten als Komponenten ausschließlich solche aus anderen Werttypen und keine Referenzen, was leicht nachvollziehbar ist.

Einfache Datentypen wie Ganzzahlen, Wahrheitswerte oder Gleitkommazahlen sind Werttypen. Trotz oder wegen gleichlautender Typnamen in anderen Programmiersprachen lauert hier allerdings eine "Falle". Im Gegensatz zu seinen Cousins erlaubt Swift als Default-Einstellung in Datentypen wie Int keinen Überlauf.

Neben den "einfachen" Typen existieren komplexere Datenstrukturen wie Zeichenketten und Verbundtypen (auch "Strukturen" genannt). Zu den benutzerdefinierten Referenztypen gehören bei einer objektorientierten Sprache hauptsächlich Klassen, aber auch Felder (Array), Hash-Tabellen (Dictionary), Tupel sowie Closures als Obermenge der Funktionen.