EMZETT.
Login

Kurz: Ein struct gruppiert Daten und Methoden. Structs sind Werttypen: Zuweisen kopiert.

Teil des Kurses Swift

Kapitel 4 von 8 im Kurs Swift (Abschnitt „Eigene Typen“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Struct: Werttyp

Ein struct gruppiert Daten und Methoden. Structs sind Werttypen: Zuweisen kopiert.

struct Punkt {
    var x: Double
    var y: Double = 0                          // Standardwert
 
    var abstand: Double { (x * x + y * y).squareRoot() }      // berechnete Eigenschaft
 
    mutating func verschiebe(dx: Double, dy: Double) {        // mutating: ändert self
        x += dx; y += dy
    }
 
    static let ursprung = Punkt(x: 0)
    func beschreibung() -> String { "(\(x), \(y))" }
}
 
var a = Punkt(x: 3, y: 4)
var b = a                                       // Kopie!
b.verschiebe(dx: 1, dy: 1)
print(a.beschreibung(), b.beschreibung(), a.abstand, Punkt.ursprung.x)
 
struct Konto {
    private(set) var stand: Double = 0
    let inhaber: String
    var historie: [Double] = []
 
    mutating func einzahlen(_ betrag: Double) {
        guard betrag > 0 else { return }
        stand += betrag
        historie.append(betrag)
    }
    init(inhaber: String, startstand: Double = 0) {
        self.inhaber = inhaber
        self.stand = startstand
    }
}
var k = Konto(inhaber: "Mia", startstand: 100)
k.einzahlen(50); k.einzahlen(-5)
print(k.inhaber, k.stand, k.historie)

Ausgabe:

(3.0, 4.0) (4.0, 5.0) 5.0 0.0
Mia 150.0 [50.0]

Klassen: Referenztyp

Eine class ist ein Referenztyp: Mehrere Variablen zeigen auf dasselbe Objekt. Klassen unterstützen Vererbung.

class Tier {
    let name: String
    init(name: String) { self.name = name }
    func laut() -> String { "..." }
    func vorstellen() -> String { "\(name) sagt \(laut())" }
}
 
class Hund: Tier {
    override func laut() -> String { "Wuff" }
    func apportiere() -> String { "\(name) holt den Ball" }
}
 
class Katze: Tier {
    var leben = 9
    override func laut() -> String { "Miau" }
    override func vorstellen() -> String { super.vorstellen() + " (\(leben) Leben)" }
}
 
let tiere: [Tier] = [Hund(name: "Rex"), Katze(name: "Mimi")]
for t in tiere { print(t.vorstellen()) }
if let h = tiere[0] as? Hund { print(h.apportiere()) }
print(tiere[1] is Katze)
 
let eins = Katze(name: "A")
let zwei = eins                                  // gleiche Instanz
zwei.leben = 3
print(eins.leben, eins === zwei)
 
class Zaehler {
    var wert = 0
    deinit { print("Zähler freigegeben") }
}
do { let z = Zaehler(); z.wert = 5 }

Ausgabe:

Rex sagt Wuff
Mimi sagt Miau (9 Leben)
Rex holt den Ball
true
3 true
Zähler freigegeben
structclass
TypWert (Kopie)Referenz
Vererbungneinja
deinitneinja
Standard in Swiftbevorzugenwenn Identität/Vererbung nötig

Swift verwaltet Klassen per ARC (automatische Referenzzählung): Es gibt keinen Garbage Collector; Zyklen vermeidet man mit weak/unowned.

Enums

Swift-Enums sind mächtig: Sie haben Methoden, Rohwerte und zugeordnete Werte.

enum Richtung: CaseIterable {
    case nord, ost, sued, west
    func gegenteil() -> Richtung {
        switch self {
        case .nord: return .sued
        case .sued: return .nord
        case .ost: return .west
        case .west: return .ost
        }
    }
}
 
enum Planet: Int { case merkur = 1, venus, erde }       // Rohwerte
 
enum Ergebnis {
    case erfolg(wert: Int)
    case fehler(grund: String)
    case laden
}
 
func zeige(_ e: Ergebnis) -> String {
    switch e {
    case .erfolg(let w): return "Wert \(w)"
    case .fehler(let g): return "Fehler: \(g)"
    case .laden: return "lädt ..."
    }
}
 
print(Richtung.nord.gegenteil(), Richtung.allCases.count, Planet.erde.rawValue, Planet(rawValue: 2) as Any)
print(zeige(.erfolg(wert: 42)), zeige(.fehler(grund: "kaputt")), zeige(.laden))
 
enum Optionaler<T> { case nichts, etwas(T) }          // Generischer Enum (so ist Optional gebaut)
print(Optionaler.etwas(5))

Ausgabe:

sued 4 3 Optional(prog.Planet.venus)
Wert 42 Fehler: kaputt lädt ...
etwas(5)

Merke

  • struct = Werttyp, bevorzugt; mutating für ändernde Methoden
  • class = Referenztyp mit Vererbung, init, deinit, ARC
  • enum mit Methoden, Rohwerten und zugeordneten Werten; switch ist vollständig
  • Berechnete Eigenschaften, static, private(set)
  • === vergleicht Identität von Objekten

Übungsaufgabe

Modelliere Formen (Kreis, Rechteck) als Enum mit zugeordneten Werten und berechne die Fläche.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Funktionen, Closures und Collections

Weiter: Protokolle, Generics, Extensions und Fehler

Alle Kapitel: Swift im Überblick