Tracks
/
Swift
Swift
/
Übungen
/
Logzeilen
Logzeilen

Logzeilen

Lernübung

Einführung

Wenn du Daten modellierst, die nur eine bestimmte Menge möglicher Zustände annehmen können (etwa Wochentage, Himmelsrichtungen oder Tasten auf einem Controller), haben einfache Typen wie Int oder String große Nachteile. Mit Ganzzahlen oder Strings muss dein Code ständig auf ungültige Werte prüfen (etwa einen Statuscode 999 oder einen Tippfehler wie "leftt"), und Menschen, die den Code lesen, können nicht leicht erkennen, wofür die Zahlen stehen.

Swift löst dieses Problem mit Aufzählungen (oft kurz Enums genannt). Ein Enum definiert einen gemeinsamen Typ für eine Gruppe verwandter, benannter Werte. Weil der Compiler alle möglichen Fälle im Voraus kennt, kann er deinen Code zur Kompilierzeit auf Korrektheit und Vollständigkeit prüfen. Enums können auch Methoden, Initialisierer und berechnete Eigenschaften haben.

Enums definieren

Definiere ein Enum mit dem Schlüsselwort enum, gefolgt vom Typnamen, und liste seine Fälle in geschweiften Klammern auf. Nach Swift-Konvention verwendet der Typname UpperCamelCase, während jeder Fall lowerCamelCase verwendet:

enum NESButton {
    case up
    case down
    case left
    case right
    case a
    case b
    case select
    case start
}

Du kannst auch mehrere Fälle in einer Zeile definieren, getrennt durch Kommas:

enum NESButton {
    case up, down, left, right, a, b, select, start
}

Um auf einen Enum-Fall zu verweisen, schreibst du den Typnamen des Enums, einen Punkt (.) und den Namen des Falls. Sobald der Typ bekannt ist oder vom Compiler abgeleitet werden kann, kannst du den Typnamen weglassen und die kürzere Punkt-Syntax verwenden:

var lastPressed = NESButton.up

// Swift infers the type, so you can omit the type name:
lastPressed = .down

let konamiCode: [NESButton] = [.up, .up, .down, .down, .left, .right, .left, .right, .b, .a]

Methoden und Initialisierer

Enums können Methoden und eigene Initialisierer definieren, genau wie Klassen und Strukturen. Innerhalb einer Enum-Methode verweist self auf den aktuellen Fallwert:

enum Coin {
    case heads
    case tails

    init(_ value: Int) {
        if value.isMultiple(of: 2) {
            self = .heads
        } else {
            self = .tails
        }
    }

    func flip() -> Coin {
        switch self {
        case .heads: return .tails
        case .tails: return .heads
        }
    }
}

let tails = Coin(13)     // .tails
let heads = Coin(0)      // .heads
let flipped = heads.flip() // .tails

Rohwerte

Enum-Fälle können mit Standardwerten vorbelegt werden, den sogenannten Rohwerten. Alle Rohwerte in einem Enum müssen denselben Typ haben (etwa Int, String oder Character):

enum NESButton: Character {
    case up = "⬆️"
    case down = "⬇️"
    case left = "⬅️"
    case right = "➡️"
    case a = "🅰️"
    case b = "🅱️"
    case select = "✅"
    case start = "🚦"
}

print(NESButton.left.rawValue) // Prints "⬅️"

Du kannst ein Enum mit init(rawValue:) aus einem Rohwert initialisieren. Weil ein ungültiger Rohwert übergeben werden könnte, gibt dieser Initialisierer ein Optional zurück:

let upButton = NESButton(rawValue: "⬆️") // Optional(NESButton.up)
let invalid = NESButton(rawValue: "🙄")  // nil

Swift kann für String- und Int-Enums automatisch Rohwerte vergeben:

  • Bei String-Enums entspricht der Rohwert jedes Falls standardmäßig seinem Fallnamen.
  • Bei Int-Enums beginnen die Rohwerte bei 0 und erhöhen sich um 1, sofern nichts anderes angegeben ist.
enum Planet: Int {
    case mercury = 1, venus, earth, mars
}

print(Planet.earth.rawValue) // Prints 3

Anleitung

In dieser Übung verarbeitest du Logzeilen.

Jede Logzeile ist ein String, der wie folgt formatiert ist: "[<LVL>]: <MESSAGE>".

Das sind die verschiedenen Log-Level:

  • TRC (trace)
  • DBG (debug)
  • INF (info)
  • WRN (warning)
  • ERR (error)
  • FTL (fatal)

Du hast drei Aufgaben, die du alle erledigen musst, um die nötige Funktionalität bereitzustellen.

1. Erstelle das LogLevel-Enum

Definiere ein LogLevel-Enum mit sechs Fällen, die den obigen Log-Leveln entsprechen, plus einem unbekannten Fall für Log-Level, die fehlen oder nicht dem Standard entsprechen.

  • trace
  • debug
  • info
  • warning
  • error
  • fatal
  • unknown

2. Log-Level parsen

Implementiere als Nächstes den Initialisierer von LogLevel, um den Log-Level einer Logzeile zu parsen:

LogLevel("[INF]: File deleted")
// Returns LogLevel.info
LogLevel("Something went wrong!")
// Returns LogLevel.unknown

3. Logzeile ins Kurzformat umwandeln

Der Log-Level einer Logzeile nimmt ziemlich viel Platz ein. Um den Speicherplatz zu reduzieren, den die Logzeilen belegen, wurde ein Kurzformat entwickelt: "<ENCODED_LEVEL>:<MESSAGE>".

Der kodierte Log-Level ist eine einfache Zuordnung eines Log-Levels zu einer Zahl:

  • trace - 0
  • debug - 1
  • info - 4
  • warning - 5
  • error - 6
  • fatal - 7
  • unknown - 42

Implementiere die Methode shortFormat(message: String) -> String, die das verkürzte Logzeilenformat als String ausgeben kann:

let overflow = LogLevel.error
overflow.shortFormat(message: "Stack overflow")
// Returns "6:Stack overflow"
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Swift Exercism

Bereit, mit Logzeilen zu starten?

Melde dich bei Exercism an, um Swift mit 35 Konzepte116 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.