Inicjalizatory, które mogą zawieść
Część sekcji Programowanie obiektowe ścieżki Swift w Coddy. Lekcja 20 z 57.
Niektórych wartości nie można utworzyć z każdego wejścia. Inicjalizator, który może się nie powieść, zapisywany jako init?, zwraca nil zamiast instancji, gdy dane wejściowe są nieprawidłowe, dzięki czemu nie może istnieć żadna nieprawidłowa instancja:
struct Percentage {
let value: Int
init?(_ value: Int) {
guard value >= 0, value <= 100 else { return nil }
self.value = value
}
}
print(Percentage(42)?.value ?? -1)
print(Percentage(150)?.value ?? -1)Wynik:
42
-1Wynik inicjalizatora zawodnego jest wartością opcjonalną, więc wywołujący musi ją rozpakować, zwykle za pomocą if let lub guard let:
struct Email {
let address: String
init?(_ text: String) {
let parts = text.split(separator: "@")
guard parts.count == 2, parts[1].contains(".") else { return nil }
address = text.lowercased()
}
}
for text in ["Ada@Mail.com", "not-an-email"] {
if let email = Email(text) {
print("valid: \(email.address)")
} else {
print("invalid: \(text)")
}
}Wynik:
valid: ada@mail.com
invalid: not-an-emailTypy Swift używają tego samego pomysłu: Int("42") i Double("x") to inicjalizatory opcjonalne, podobnie jak init(rawValue:) enuma. Inicjalizator opcjonalny może je wywołać i przekazać dalej informację o niepowodzeniu:
struct Coordinate {
let lat: Double
let lon: Double
init?(text: String) {
let parts = text.split(separator: ",")
guard parts.count == 2,
let lat = Double(parts[0]), let lon = Double(parts[1]),
abs(lat) <= 90, abs(lon) <= 180 else { return nil }
self.lat = lat
self.lon = lon
}
}
print(Coordinate(text: "51.5,-0.1") != nil)
print(Coordinate(text: "95,10") != nil)Wynik:
true
falseUżyj init?, gdy brakująca wartość jest wystarczającą informacją. Użyj inicjalizatora zgłaszającego błąd, init(...) throws, gdy wywołujący powinien dowiedzieć się, która reguła nie została spełniona:
struct Username {
let text: String
init(_ text: String) throws {
guard text.count >= 3 else { throw NameError.tooShort }
guard text.allSatisfy({ $0.isLetter }) else { throw NameError.badCharacters }
self.text = text
}
}Wyzwanie
ŁatwyUzupełnij strukturę Rgb, która przechowuje kolor jako składowe red, green i blue o wartościach od 0 do 255. Jej inicjalizator failable init?(hex:) odczytuje tekst, taki jak #FF8000: zwraca nil, chyba że tekst składa się z #, po którym następuje dokładnie sześć cyfr szesnastkowych. Użyj Int(text, radix: 16) dla każdej pary. Dodaj obliczaną właściwość label, która zwraca rgb(255, 128, 0).
Dostarczony kod odczytuje jeden kolor w każdym wierszu i wypisuje etykietę albo invalid: text.
Twój kod umieść w pliku Rgb.swift. Plik main.swift zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
// Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
if let color = Rgb(hex: line) {
print(color.label)
} else {
print("invalid: \(line)")
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasMetody i selfInicjalizatoryKlasy są referencjamiPowtórzenie — karta biblioteczna4Hermetyzacja
Kontrola dostępuTylko do odczytu z zewnątrzOchrona stanuInicjalizatory, które mogą zawieśćPodsumowanie — konto bankowe7Polimorfizm i typy generyczne
PolimorfizmRzutowanie typówFunkcje generyczneTypy generycznePodsumowanie – kalkulator kształtów2Struktury i typy wartościowe
StrukturySemantyka wartościMetody modyfikująceStruktura czy klasaPodsumowanie – element inwentarza5Dziedziczenie
PodklasyPrzesłanianie metodInicjalizatory i superfinal i hierarchiePodsumowanie — hierarchia pracowników8Standardowe protokoły
CustomStringConvertibleEquatableComparableHashablePodsumowanie — własne sortowanie11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Edytor online Swift