Kapitel 2: Grundlagen / 2.8 Tupel

Mit Tupeln (engl.: one tuple, more tuples) bietet Swift die Möglichkeit, in einer Variablen mehrere Werte zu speichern. Diese Werte können jeder für sich einen beliebigen Typ haben. Es ist also zum Beispiel kein Problem einen String mit einem Integer zu einem Tupel zu kombinieren:

let captain: (String, Int) = ("Jean-Luc Picard", 58)

Hier werden in der Konstanten captain der Name und das Alter des Captains gespeichert. Da Type Inference auch für Tupel funktioniert, können Sie anstelle der obigen Deklaration auch schlicht folgendes schreiben:

let captain = ("Jean-Luc Picard", 58)

In diesem Beispiel wird der Typ von captain als (String, Int) inferiert. Wie bereits gesagt, hält Sie aber auch nichts davon ab, Tupel zum Beispiel vom Typ (Double, Double, Double) oder (Bool, String) zu verwenden.

Die einzelnen Werte innerhalb eines Tupels werden von Swift automatisch durchnummeriert. Sie können das sehen, wenn Sie eine der beiden obenstehenden Deklarationen in einen Playground eingeben; rechts neben der Deklaration steht dann nämlich:

(.0 "Jean-Luc Picard", .1 58)

Nummeriert in der Reihenfolge ihres Auftretens, wird dem Wert "Jean-Luc Picard" die Nummer 0 zugeordnet und dem Wert 58 die Nummer 1.

In der Programmierung heißt eine solche Nummerierung Index. Typischerweise, wie ja auch hier, beginnt die Zählung bei einem Index mit 0 und nicht mit 1.

Der Punkt vor der Nummer im Playground weist darauf hin, wie sie nun die einzelnen Werte wieder aus dem Tupel herauslesen können:

Variante 1: Verwendung des Index

let nameDesCaptains: String = captain.0
let alterDesCaptains: Int = captain.1
println ("Captain \(nameDesCaptains) ist \(alterDesCaptains) Jahre alt.")

oder alternativ auch in nur einer Zeile:

println ("Captain \(captain.0) ist \(captain.1) Jahre alt.")

Beides führt zu der Ausgabe:

Captain Jean-Luc Picard ist 58 Jahre alt.

Variante 2: Verwendung der Benennung

Sie können die Einzelwerte innerhalb eines Tupels bereits bei der Deklaration benennen und dann darüber auf diese zugreifen. Dies ist die Variante, die ich Ihnen ans Herz legen möchte, da genauso wie es sinnvoll ist, Variablen sprechend zu benennen, es auch sinnvoll ist, dies bei den Einzelwerten eines Tupels zu tun, damit nämlich der Code verständlich bleibt. In unserem Beispiel sähe das so aus:

let captain = (name: "Jean-Luc Picard", alter: 58)
println ("Captain \(captain.name) ist \(captain.alter) Jahre alt.“)

 

 Variante 3: Verwendung von Dekomposition

Eine dritte Variante, auf die Einzelwerte eines Tupels zuzugreifen ist die Dekomposition (engl.: decomposition). Hierbei wird die Klammer- und Kommaschreibweise rechts des Gleichheitszeichens auch links des Gleichheitszeichens verwendet, um einen Tupel in die Einzelwerte aufzuspalten:

// Deklariere ein Tupel
let captain = ("Jean-Luc Picard", 58)
// Dekomponiere das Tupel in zwei neue Konstanten
let (name, alter) = captain
// Gib diese beiden neuen Konstanten aus
println ("Captain \(name) ist \(alter) Jahre alt.")

Hierbei muss natürlich die Anzahl der zu deklarierenden Konstanten oder Variablen links des Gleichheitszeichens mit der Anzahl der Werte innerhalb des Tupels übereinstimmen. Folgendes geht also nicht:

let (name, alter, sonst) = captain

Da captain aus nur zwei Werten besteht, führt dies zu der Fehlermeldung:

Tuple Types .. have a different number of elements (2 vs. 3)

Oder auf deutsch: Die Tupel-Typen haben eine unterschiedliche Anzahl Elemente (2 gegenüber 3).

Es ist allerdings möglich, durch Dekomposition auch weniger Werte aus einem Tupel herauszulösen, als dieses eigentlich enthält. Hierbei wird anstelle der uninteressanten Werte ein Unterstrich verwendet:

let (name, _) = captain
println ("Der Captain heißt \(name).")

Für diejenigen, die bereits mit Klassen und Funktionen etwas anfangen können, möchte ich noch etwas hinzufügen:

Tupel sind besonders im Zusammenhang mit Funktionen interessant, die traditionell zwar viele Eingabewerte (Parameter) haben können, aber nur einen Rückgabewert. Um mehrere Werte zurückgeben zu können, wurden vor Swift oft eigene Objekte verwendet, für die allerdings zuvor eigens Klassen geschrieben werden mussten, ein ziemlich umständliches Vorgehen. Swift verkürzt das, indem Tupel es ermöglichen, ad hoc ein Objekt aufzubauen und dieses zurückzugeben, ohne erst eine Klasse schreiben zu müssen. Die Ähnlichkeit zu Objekten erkennt man gut an der Punkt-Schreibweise: Über objekt.eigenschaft wird auch auf die Eigenschaften von Objekten zugegriffen, die durch das instantiieren einer Klasse entstanden sind.

Apple weist in diesem Zusammenhang darauf hin – und ich will das gerne unterstreichen – dass Tupel gut geeignet sind, um auf die Schnelle Werte zu gruppieren, die miteinander in Zusammenhang stehen. Sie eignen sich jedoch nicht so gut, um dauerhafte und/oder komplexe Datenstrukturen abzubilden. Dafür sollten nach wie vor Klassen oder Strukturen verwendet werden.

Für diejenigen, denen das noch nichts sagt: In späteren Kapiteln werden wir uns ausführlich mit Klassen, Strukturen und Funktionen beschäftigen, dann kommen wir auf dieses Thema noch einmal zurück.

Kapitel 2.8: Tupel

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.