Инициализаторы с возможностью сбоя
Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 20 из 57.
Некоторые значения нельзя создать из любых входных данных. Инициализатор, допускающий сбой, записываемый как init?, возвращает nil вместо экземпляра, если входные данные недействительны, поэтому недействительный экземпляр никогда не может существовать:
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)Вывод:
42
-1Результат инициализатора, который может завершиться неудачей, является опциональным значением, поэтому вызывающий код должен распаковать его, обычно с помощью if let или 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)")
}
}Результат:
valid: ada@mail.com
invalid: not-an-emailСобственные типы Swift используют ту же идею: Int("42") и Double("x") — это инициализаторы, которые могут завершиться неудачей, как и init(rawValue:) перечисления. Инициализатор, который может завершиться неудачей, может вызвать их и передать ошибку дальше:
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)Вывод:
true
falseИспользуйте init?, когда отсутствующее значение — это достаточная информация. Используйте инициализатор, выдающий ошибку, init(...) throws, когда вызывающему коду нужно узнать, какое правило не выполнено:
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
}
}Задание
ЛегкоДополните структуру Rgb, которая хранит цвет как значения red, green и blue от 0 до 255. Её инициализатор, допускающий сбой, init?(hex:) считывает текст вроде #FF8000: он возвращает nil, если текст не состоит из #, за которым следуют ровно шесть шестнадцатеричных цифр. Используйте Int(text, radix: 16) для каждой пары. Добавьте вычисляемое свойство label, которое возвращает rgb(255, 128, 0).
Предоставленный код считывает по одному цвету в каждой строке и выводит метку или invalid: text.
Ваш код должен находиться в Rgb.swift. В main.swift содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
// Предоставленный код ввода/вывода: оставьте его как есть
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)")
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовМетоды и selfИнициализаторыКлассы — это ссылкиПовторение — читательский билет4Инкапсуляция
Контроль доступаТолько чтение извнеЗащита состоянияИнициализаторы с возможностью сбояПовторение — банковский счёт7Полиморфизм и обобщения
ПолиморфизмПриведение типовОбобщённые функцииОбобщённые типыПовторение — калькулятор фигур10Паттерны проектирования. Часть 2
Паттерн делегированияПаттерн декораторПаттерн строительПаттерн состояния2Структуры и типы-значения
СтруктурыСемантика значенийИзменяющие методыСтруктура или классПовторение — элемент инвентаря5Наследование
ПодклассыПереопределение методовИнициализаторы и superfinal и иерархииПовторение — иерархия сотрудников8Стандартные протоколы
CustomStringConvertibleEquatableComparableHashableПовторение — пользовательская сортировка11Проект: Управление библиотекой
Книги и читателиВыдача книгПотренируйтесь самостоятельно: Песочница Swift