Swift. Подробно
Покупка
Новинка
Издательство:
ДМК Пресс
Автор:
Вейн Чейрд
Перевод:
Беликов Д. А.
Год издания: 2020
Кол-во страниц: 412
Дополнительно
Вид издания:
Практическое пособие
Уровень образования:
Профессиональное образование
ISBN: 978-5-97060-780-0
Артикул: 799584.02.99
Доступ онлайн
В корзину
Данная книга знакомит вас с навыками, необходимыми для создания профессионального программного обеспечения для платформ Apple, таких как iOS и MacOS. Вы освоите такие мощные методы, как обобщение, эффективная обработка ошибок, протокольно-ориентированное программирование и современные шаблоны Swift. Издание рассчитано на программистов продвинутого и среднего уровней.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
- 09.03.03: Прикладная информатика
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов.
Для полноценной работы с документом, пожалуйста, перейдите в
ридер.
Чейрд ин’т Вейн Swift. Подробно
Tjeerd in ‘t Veen Swift in Depth New York, 2019
Чейрд ин’т Вейн Swift. Подробно Москва, 2020
УДК 004.432 ББК 32.972.1 B26 B26 Чейрд ин’т Вейн Swift. Подробно / Пер. с англ. Д. А. Беликова. – М.: ДМК Пресс, 2020. – 412 с. ISBN 978-5-97060-780-0 Данная книга знакомит вас с навыками, необходимыми для создания профессионального программного обеспечения для платформ Apple, таких как iOS и MacOS. Вы освоите такие мощные методы, как обобщение, эффективная обработка ошибок, протокольно-ориентированное программирование и современные шаблоны Swift. Издание рассчитано на программистов продвинутого и среднего уровней. УДК 004.432 ББК 32.972.1 Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав Материал, изложенный в данной книге, многократно проверен. Но, поскольку вероятность технических ошибок все равно существует, издательство не может гарантировать абсолютную точность и правильность приводимых сведе ний. В связи с этимиздательство не несет ответственности за возможные ошибки, связанные с использованием книги. ISBN 978-5-97060-780-0 (рус.) ©2019 by Manning Publications Co. ISBN 978-1-61729-518-8 (анг.) © Оформление, издание, ДМК Пресс, 2020
Содержание Предисловие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Благодарности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Об этой книге . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Почему эта книга? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Подходит ли вам эта книга? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Чем эта книга не является . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Особый акцент на практических сценариях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Дорожная карта . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 О коде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Книжный форум . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Об авторе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Об иллюстрации на обложке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Предисловие от издательства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Отзывы и пожелания . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Список опечаток . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Нарушение авторских прав . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Глава 1. Введение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.1. «Золотая середина» SWIFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.2. Под поверхностью . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 1.3. Минусы Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 1.3.1. Стабильность ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 1.3.2. Строгость . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.3.3. Сложность протоколов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.3.4. Параллелизм . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 1.3.5. Отход от платформ Apple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.3.6. Время компиляции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.4. Чему вы научитесь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1.5. Как извлечь максимум из этой книги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1.6. Минимальная квалификация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 1.7. Версия Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Глава 2. Моделирование данных с помощью перечислений . . . . . . . . . . . . . . . . . . . . . 37 2.1. OR в сравнении с AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 2.1.1. Моделирование данных с помощью структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 2.1.2. Превращаем структуру в перечисление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.1.3. Выбор между структурами и перечислениями . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 2.2. Перечисления для полиморфизма . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.2.1. Полиморфизм на этапе компиляции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.3. Перечисления вместо создания подклассов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.3.1. Формирование модели для приложения Workout . . . . . . . . . . . . . . . . . . . . . . . . . 47 2.3.2. Создание суперкласса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 2.3.3. Недостатки подклассов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 2.3.4. Рефакторинг модели данных с помощью перечислений . . . . . . . . . . . . . . . . . . . 49
Содержание 2.3.5. Подклассы или перечисления – что выбрать . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.3.6. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.4. Алгебраические типы данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.4.1. Типы-суммы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 2.4.2. Типы-произведения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.4.3. Распределение суммы в перечислении . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.4.4. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 2.5. Более безопасное использование строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 2.5.1. Опасность необработанных значений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 2.5.2. Сопоставление для строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 2.5.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 2.6. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Глава 3. Написание более чистых свойств . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.1. Вычисляемые свойства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.1.1. Моделирование упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 3.1.2. Преобразование функций в вычисляемые свойства . . . . . . . . . . . . . . . . . . . . . . . 68 3.1.3. Завершение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.2. Ленивые свойства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.2.1. Создание учебного плана . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.2.2. Когда вычисляемые свойства не помогают . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 3.2.3. Использование ленивых свойств . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 3.2.4. Делаем ленивое свойство устойчивым . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 3.2.5. Изменяемые и ленивые свойства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 3.2.6. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 3.3. Наблюдатели свойств . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.3.1. Обрезка пробелов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.3.2. Запуск наблюдателей свойств из инициализаторов . . . . . . . . . . . . . . . . . . . . . . . 81 3.3.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 3.4. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Глава 4. Делаем опционалы второй натурой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 4.1. Назначение опционалов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 4.2. Чистое извлечение значений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 4.2.1. Сопоставление для опционалов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 4.2.2. Методы извлечения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 4.2.3. Когда значение вас не интересует . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.3. Сокрытие переменной . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 4.3.1. Реализация протокола CustomStringConvertible . . . . . . . . . . . . . . . . . . . . . . . . . . 93 4.4. Когда опционалы запрещены . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 4.4.1. Добавление вычисляемого свойства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 4.5. Возврат опциональных строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 4.6. Детальный контроль над опционалами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 4.6.1. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 4.7. Откат назад, если опционал равен nil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 4.8. Упрощение опциональных перечислений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 4.8.1. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Содержание 7 4.9. Цепочки опционалов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 4.10. Ограничение опциональных логических типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 4.10.1. Сокращение логического типа до двух состояний . . . . . . . . . . . . . . . . . . . . . . 104 4.10.2. Откат к значению true . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 4.10.3. Логический тип данных с тремя состояниями . . . . . . . . . . . . . . . . . . . . . . . . . . 105 4.10.4. Реализация протокола RawRepresentable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 4.10.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 4.11. Рекомендации по принудительному извлечению значения . . . . . . . . . . . . . . . . 108 4.11.1. Когда принудительное извлечение значения является «приемлемым» . . . . 109 4.11.2. Аварийный сбой со стилем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 4.12. Приручаем неявно извлекаемые опционалы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 4.12.1. Как распознать неявно извлекаемый опционал . . . . . . . . . . . . . . . . . . . . . . . . 111 4.12.2. Неявно извлекаемые опционалы на практике . . . . . . . . . . . . . . . . . . . . . . . . . . 111 4.12.3. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 4.13. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Глава 5. Разбираемся с инициализаторами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117 5.1. Правила инициализаторов структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 5.1.1. Пользовательские инициализаторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 5.1.2. Странность инициализатора структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 5.1.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 5.2. Инициализаторы и подклассы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 5.2.1. Создание суперкласса настольной игры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 5.2.2. Инициализаторы BoardGame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 5.2.3. Создание подкласса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 5.2.4. Потеря вспомогательных инициализаторов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 5.2.5. Возвращение инициализаторов суперкласса . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 5.2.6. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 5.3. Минимизация инициализаторов класса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 5.3.1. Реализация назначенного инициализатора в качестве вспомогательного с использованием ключевого слова override . . . . . . . . . . . 130 5.3.2. Деление подкласса на подклассы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 5.3.3. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.4. Требуемые инициализаторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.4.1. Фабричные методы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.4.2. Протоколы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 5.4.3. Когда классы являются финальными . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 5.4.4. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 5.5. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Глава 6. Непринужденная обработка ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .142 6.1. Ошибки в Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 6.1.1. Протокол Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 6.1.2. Генерация ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 6.1.3. Swift не показывает ошибки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 6.1.4. Сохранение среды в предсказуемом состоянии . . . . . . . . . . . . . . . . . . . . . . . . . 147
Содержание 6.1.5. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 6.2. Распространение ошибок и перехват . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 6.2.1. Распространение ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 6.2.2. Добавление технических деталей для устранения неполадок . . . . . . . . . . . . . 154 6.2.3. Централизация обработки ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.2.4. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 6.3. Создание симпатичных API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 6.3.1. Сбор достоверных данных в типе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 6.3.2. Ключевое слово try? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 6.3.3. Ключевое слово try! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 6.3.4. Возвращение опционалов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 6.3.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 6.4. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Глава 7. Обобщения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .168 7.1. Преимущества обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 7.1.1. Создание обобщенной функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 7.1.2. Рассмотрение обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 7.1.3. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 7.2. Ограничение обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 7.2.1. Нужна функция ограничения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 7.2.2. Протоколы Equatable и Comparable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 7.2.3. Ограничивать значит специализировать . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 7.2.4. Реализация протокола Comparable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 7.2.5. Ограничение в сравнении с гибкостью . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 7.3. Ряд ограничений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 7.3.1. Протокол Hashable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 7.3.2. Комбинируем ограничения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 7.3.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 7.4. Создание обобщенного типа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 7.4.1. Желание совместить два типа, соответствующих протоколу Hashable . . . . . . 183 7.4.2. Создание типа Pair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 7.4.3. Несколько обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 7.4.4. Соответствие протоколу Hashable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 7.4.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 7.5. Обобщения и подтипы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 7.5.1. Подтипы и инвариантность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 7.5.2. Инвариантность в Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 7.5.3. Универсальные типы Swift получают особые привилегии . . . . . . . . . . . . . . . . . 190 7.6. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 Глава 8. Становимся профессионалами в протокольно-ориентированном программировании . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .194 8.1. Время выполнения в сравнении со временем компиляции . . . . . . . . . . . . . . . . . . . . 195 8.1.1. Создание протокола . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8.1.2. Обобщения в сравнении с протоколами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Содержание 9 8.1.3. Находим компромисс . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 8.1.4. Переход ко времени выполнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 8.1.5. Выбор между временем компиляции и временем выполнения . . . . . . . . . . . . 199 8.1.6. Когда обобщение – лучший вариант . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.1.7. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 8.2. Зачем нужны ассоциированные типы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 8.2.1. Недостатки протоколов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 8.2.2. Попытка превратить все в протокол . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 8.2.3. Разработка обобщенного протокола . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 8.2.4. Моделирование протокола с ассоциированными типами . . . . . . . . . . . . . . . . . 206 8.2.5. Реализация протокола с ассоциированными типами . . . . . . . . . . . . . . . . . . . . . 207 8.2.6. Протоколы с ассоциированными типами в стандартной библиотеке . . . . . . . 209 8.2.7. Другие случаи использования ассоциированных типов . . . . . . . . . . . . . . . . . . 209 8.2.8. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 8.3. Передача протокола с ассоциированными типами . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 8.3.1. Использование оператора where с ассоциированными типами . . . . . . . . . . . 212 8.3.2. Типы, ограничивающие ассоциированные типы . . . . . . . . . . . . . . . . . . . . . . . . . 213 8.3.3. Очистка API и наследование протокола . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 8.3.4. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 8.4. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Глава 9. Итераторы, последовательности и коллекции . . . . . . . . . . . . . . . . . . . . . . . . .221 9.1. Итерация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 9.1.1. Циклы и метод makelterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 9.1.2. IteratorProtocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 9.1.3. Протокол Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 9.1.4. Посмотрим поближе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 9.2. Сила Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 9.2.1. Метод filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 9.2.2. Метод forEach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 9.23. Метод enumerated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 9.2.4. Ленивая итерация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 9.2.5. Метод reduce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 9.2.6. Метод reduce into . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 9.2.7. Метод zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 9.2.8. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 9.3. Создание обобщенной структуры данных с помощью Sequence . . . . . . . . . . . . . . . 233 9.3.1. Bag в действии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 9.3.2. Создаем BagIterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 9.3.3. Реализация AnyIterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 9.3.4. Реализация ExpressibleByArrayLiteral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 9.3.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 9.4. Протокол Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 9.4.1. Ландшафт Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 9.4.2. MutableCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Содержание 9.4.3. RangeReplaceableCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 9.4.4. BidirectionalCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 9.4.5. RandomAccessCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 9.5. Создание коллекции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 9.5.1. Создание плана поездки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 9.5.2. Реализация Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 9.5.3. Пользовательские сабскрипты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 9.5.4. ExpressibleByDictionaryLiteral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 9.5.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 9.6. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Глава 10. map, flatMap и compactMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .255 10.1. Знакомство с map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 10.1.1. Создание конвейера с помощью метода map . . . . . . . . . . . . . . . . . . . . . . . . . . 258 10.1.2. Использование метода map для словарей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 10.1.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 10.2. Последовательности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 10.2.1. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 10.3. Использование метода map для опционалов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 10.3.1. Когда использовать метод map с опционалами . . . . . . . . . . . . . . . . . . . . . . . . . 264 10.3.2. Создание обложки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 10.3.3. Более короткий вариант нотации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 10.3.4. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 10.4. map – это абстракция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 10.5. Овладеваем методом flatMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 10.5.1. В чем преимущества flatMap? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 10.5.2. Когда метод map не подходит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 10.5.3. Борьба с пирамидой гибели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 10.5.4. Использование метода flatMap с опционалом . . . . . . . . . . . . . . . . . . . . . . . . . . 275 10.6. flatMap и коллекции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 10.6.1. flatMap и строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 10.6.2. Сочетание flatMap и map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 10.6.3. compactMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 10.6.4. Вложенность или цепочки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 10.6.5. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 10.7. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Глава 11. Асинхронная обработка ошибок с помощью типа Result . . . . . . . . . . . . . . .290 11.1. Зачем использовать тип Result? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 11.1.1. Как раздобыть Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 11.1.2. Result похож на Optional, но с изюминкой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 11.1.3. Преимущества Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 11.1.4. Создание API с использованием типа Result . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 11.1.5. Из Cocoa Touch в Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 11.2. Распространение Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 11.2.1. Создание псевдонимов типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Содержание 11 11.2.2. Функция search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 11.3. Преобразование значений внутри Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 11.3.1. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 11.3.2. Использование метода flatMap для типа Result . . . . . . . . . . . . . . . . . . . . . . . . . 304 11.3.3. Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 11.4. Смешивание Result с функциями, генерирующими ошибку . . . . . . . . . . . . . . . . . . . 307 11.4.1. От генерации ошибки к типу Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 11.4.2. Преобразование генерирующей функции внутри flatMap . . . . . . . . . . . . . . . 309 11.4.3. Пропускаем ошибки через конвейер . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 11.4.4. Подходя к концу . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 11.4.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 11.5. Несколько ошибок внутри Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 11.5.1. Знакомство с AnyError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 11.6. Невообразимый провал и Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 11.6.1. Когда протокол определяет Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 11.7. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Глава 12. Расширения протоколов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .325 12.1. Наследование классов в сравнении с наследованием протоколов . . . . . . . . . . . . 326 12.1.1. Моделирование данных по горизонтали, а не по вертикали . . . . . . . . . . . . . 327 12.1.2. Создание расширения протокола . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 12.1.3. Несколько расширений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 12.2. Наследование в сравнении с композицией . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 12.2.1. Протокол Mailer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 12.2.2. Наследование протокола . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 12.2.3. Композиционный подход . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 12.2.4. Высвобождаем энергию пересечения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 12.2.5. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 12.3. Переопределение приоритетов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 12.3.1. Переопределение реализации по умолчанию . . . . . . . . . . . . . . . . . . . . . . . . . . 336 12.3.2. Переопределение и наследование протоколов . . . . . . . . . . . . . . . . . . . . . . . . . 337 12.3.3. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 12.4. Расширение в двух направлениях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 12.4.1. Выбор расширений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 12.4.2. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 12.5. Расширение с использованием ассоциированных типов . . . . . . . . . . . . . . . . . . . . . 341 12.5.1. Специализированное расширение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 12.5.2. Недостаток расширения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 12.6. Расширение с конкретными ограничениями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 12.7. Расширение протокола Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 12.7.1. Заглянем внутрь метода filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 12.7.2. Создание метода take (while :) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 12.7.3. Создание метода Inspect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 12.7.4. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 12.8. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Содержание Глава 13. Шаблоны Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .354 13.1. Внедрение зависимости . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 13.1.1. Замена реализации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 13.1.2. Передача пользовательской версии Session . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 13.1.3. Ограничение ассоциированного типа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 13.1.4. Замена реализации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 13.1.5. Модульное тестирование и мокирование с использованием ассоциированных типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 13.1.6. Использование типа Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 13.1.7. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 13.2. Условное соответствие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 13.2.1. Бесплатная функциональность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 13.2.2. Условное соответствие для ассоциированных типов . . . . . . . . . . . . . . . . . . . . 365 13.2.3. Делаем так, чтобы Array условно соответствовал пользовательскому протоколу . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 13.2.4. Условное соответствие и обобщения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 13.2.5. Условное соответствие для типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 13.2.6. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 13.3. Что делать с недостатками . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 13.3.1. Как избежать использования перечисления . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 13.3.2. Стирание типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 13.3.3. Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 13.4. Альтернатива протоколам . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 13.4.1. Чем мощнее, тем хуже код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 13.4.2. Создание обобщенной структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 13.4.3. Эмпирические правила полиморфизма . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 13.5. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 Глава 14. Написание качественного кода на языке Swift . . . . . . . . . . . . . . . . . . . . . . . .387 14.1. Документация по API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 14.1.1. Как работает Quick Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 14.1.2. Добавление выносок в Quick Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 14.1.3. Документация в качестве HTML с использованием Jazzy . . . . . . . . . . . . . . . . 391 14.2. Комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 14.2.1. Объясняем причину . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 14.2.2. Объясняем только непонятные элементы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 14.2.3. Код несет истину . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 14.2.4. Комментарии – не повязка для неудачных имен . . . . . . . . . . . . . . . . . . . . . . . 393 14.2.5. Зомби-код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 14.3. Правила стиля . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 14.3.1. Согласованность – это ключ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 14.3.2. Обеспечение соблюдения правил с помощью линтера . . . . . . . . . . . . . . . . . . 395 14.3.3. Установка SwiftLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 14.3.4. Настройка SwiftLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 14.3.5. Временное отключение правил SwiftLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 14.3.6. Автозамена правил SwiftLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Содержание 13 14.3.7. Синхронизация SwiftLint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 14.4. Избавляемся от менеджеров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 14.4.1. Ценность менеджеров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 14.4.2. Атака на менеджеров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 14.4.3. Прокладываем дорогу для обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 14.5. Именование абстракций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 14.5.1. Обобщенное или конкретное . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 14.5.2. Хорошие имена не меняются . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 14.5.3. Именование обобщений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 14.6. Контрольный список . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 14.7. В заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Глава 15. Что дальше? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .407 15.1. Создавайте фреймворки, предназначенные для Linux . . . . . . . . . . . . . . . . . . . . . . . 407 15.2. Изучите диспетчер пакетов Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407 15.3. Изучайте фреймворки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 15.4. Бросьте себе вызов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 15.4.1. Присоединяйтесь к эволюции Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 15.4.2. Заключительные слова . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 Предметный указатель . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .410
Предисловие Я начинал как разработчик iOS в 2011 году. Мне нравилось создавать приложения для iPhone, и я до сих пор занимаюсь этим. Помимо разработки мобильных приложений, я также занимался веб-разработкой, изучая Ruby. Мне нравился этот короткий мощный язык, и я хотел использовать компилируемый язык, такой как Objective-C, но с элегантностью и выразительностью Ruby. Затем компания Apple представила Swift, и похоже, они услышали меня. Для меня Swift был новым подходом к программированию, сочетая элегантность динамического языка со скоростью и безопасностью языка статического. Мне никогда не нравился синтаксис Objective-C. Раньше я говорил что-то вроде: «Да, Objective-C многословен, но он делает свою работу». Однако при работе со Swift я снова нахожу чтение и написание кода очень приятным занятием, как в случае с Ruby. Наконец-то я мог использовать статический язык и продолжать работать, при этом любя язык, с которым я работаю. Для меня это была хорошая комбинация. Однако это не была любовь с первого взгляда. До того, как я действительно стал наслаждаться Swift, я много с ним боролся. Swift выглядит очень дружелюбно, но, боже, иногда было тяжело. На этапе компиляции все должно быть безопасно, и я больше не мог смешивать и сопоставлять типы в массивах. Между тем Swift был только ранней версией и постоянно менялся; было трудно идти в ногу с ним. «Что такое генераторы? О, их теперь называют итераторами? А зачем использовать оператор guard? Разве нельзя вместо этого использовать оператор if? Пфф, опцио налы переоценены; можно использовать простую проверку на nil?» и т. д. Я даже не и думал о работе с обобщениями. Тем не менее я выстоял и начал принимать эти концепции Swift. Я понял, что это были более старые концепции из других языков программирования, но в новом обличье, что действительно помогло мне лучше программировать и качественнее выполнять свою работу. Со временем я начал любить язык Swift и его милый синтаксис. Начиная с Swift 2 я имел возможность поработать в большой компании, где мы производили код Swift в больших масштабах, начиная с команды, состоящей из примерно 20 разработчиков и заканчивая более чем 40. После работы со Swift при таком количестве разработчиков и после участия в сотнях запросов на принятие изменений я заметил, что у других разработчиков была такая же борьба, как и у меня. Либо мои коллеги писали просто отличный код, но не понимали, что от них скрыта более элегантная или надежная альтернатива, ждущая своего часа. Несмотря на то что наш код был верным, иногда он мог бы быть несколько чище, лаконичнее или чуть безопаснее. Я также заметил, что мы все держались подальше от мощных методов, таких как обобщения или метод flatMap, потому что их было трудно понять. Или же нам нравилась идея обобщений, но мы сами не знали, зачем и когда применять ее. После этих реализаций я начал вести записи. Поначалу эти каракули были для меня заметками о том, как правильно извлекать опиционалы, как работают ленивые свойства, как обращаться с обобщениями и т. д. Затем эти заметки созрели,
Предисловие 15 и, прежде чем я это понял, у меня было достаточно содержания для некоторых глав. Пришло время превратить эти заметки во что-то более сложное: книгу по программированию, которая может помочь другим сократить их путешествие по Swift. Имея на руках несколько сырых глав, я задавался вопросом, стоит ли мне выложить электронную книгу онлайн. Тем не менее при наличии «впечатляющих» 200 человек, подписавшихся на меня в Twitter, и не имея популярного блога, я решил, что не найду нужную аудиторию. Более того, я подумал, что мне нужно узнать много неизвестного о написании книги. Я решил обратиться к издателю, чтобы он помог мне превратить эти грубые главы в большую книгу. Я обратился в издательство Manning, и с тех пор мы вместе работаем над книгой. Полагаю, что эти «маленькие заметки» превратились в нечто особенное. С помощью друзей Manning и Swift больше года я проводил большую часть своего свободного времени, сочиняя, полируя и пытаясь сделать сложные концепции Swift более простыми для понимания. Я надеюсь, что когда вы будете читать эту книгу, она поможет вам стать мастером Swift. Надеюсь, что эта книга сделает ваше путешествие по Swift легким и увлекательным. Чейрд ин’т Вейн Благодарности Спасибо издательству Manning за то, что помогло мне опубликовать мою первую книгу. Я хочу выразить особую благодарность Майку Стивенсу за то, что он воспользовался шансом, взяв меня на борт. Спасибо Хелен Стергиус за то, что работала со мной на протяжении всего этого процесса. Спасибо Алену Куньо за великолепные технические обзоры моих глав; нелегко постоянно указывать на ошибки и возможные улучшения; тем не менее я очень ценю это. И я также хочу поблагодарить Александра Павлицкого за его креативные мультипликационные иллюстрации, использованные на протяжении всей книги. Мне очень помогли остальные члены команды Manning: Александар Драгосав- левич, Кэндис Гилхулли, Ана Ромак, Шерил Вейсман, Дейрдре Хиам, Дотти Мар- сико, Николь Борода, Мэри Пирджи, Кэрол Шилдс, Даррен Мейсс, Мелоди Долаб и Мария Тудор (Aleksandar Dragosavljević, Candace Gillhoolley, Ana Romac, Cheryl Weisman, Deirdre Hiam, Dottie Marsico, Nichole Beard, Mary Piergies, Carol Shields, Darren Meiss, Melody Dolab, Marija Tudor). Я хочу выразить особую благодарность друзьям, коллегам и тем, кто были моими подопытными свинками и рецензировали ( частично) эту книгу, в частности это: Барт ден Холландер, Димитар Гюров, Дарио де Роза, Рейн Спейккерман, Янина Кутын, Сидни де Конинг, Торбен Шульц и Эдвин Чун Винг Квок (Bart den Hollander, Dimitar Gyurov, Dario de Rosa, Rein Spijkerman, Janina Kutyn, Sidney de Koning, Torben Schulz, and Edwin Chun Wing Kwok). Также я бы хотел поблагодарить других рецензентов: Алессандро Кампей- са, Али Накви, Акселя Реста, Дэвида Джейкобса, Густаво Гомеса, Хельмута Райте- рера, Джейсона Пайка, Джона Монтгомери, Кента Р. Шпилнера, Ларса Петерсена,
Предисловие Марсело Пиреса, Марко Джузеппе Салафию, Мартин Филипп, Моника Гимарайнш, Патрик Риган, Тайлер Слэйтер и Вейерт де Бур (Alessandro Campeis, Ali Naqvi, Axel Roest, David Jacobs, Gustavo Gomes, Helmut Reiterer, Jason Pike, John Montgomery, Kent R. Spillner, Lars Petersen, Marcelo Pires, Marco Giuseppe Salafia, Martin Philp, Monica Guimaraes, Patrick Regan, Tyler Slater, and Weyert de Boer). Я знал, что написание книги – дело непростое, но это было гораздо сложнее, чем я себе представлял. У нас с моей невестой Дженикой только что родилась дочь, и было довольно сложно создавать новую семью, проводить бессонные ночи, сохранить работу на полную ставку и писать книгу по программированию на втором языке. Я бы не смог этого сделать, если бы мне не нравилось писать эту книгу при поддержке своей невесты. Спасибо, Дженика, за то, что ты так терпелива ко мне. Об этой книге Swift – это молодой язык. На момент написания данных строк вышла четвертая версия, и она все еще не является ABI-стабильной, а это означает, что после выхода Swift 5 будут существенные изменения. Так почему же эта книга может рассказать вам, как написать свой код? Ваш скептицизм был бы оправдан, но, пожалуйста, не торопитесь. Несмотря на то что Swift – относительно новый язык, я думаю, было бы справедливо сказать, что некоторые решения работают лучше, чем другие. Это еще важнее понимать, если вы используете Swift для реальных производственных приложений. Swift заимствует множество важных концепций из других языков программирования, таких как Haskell, Ruby, Rust, Python, C # и др. Следовательно, было бы разумно следить за этими концепциями. Сочетая парадигмы программирования с реальным опытом, эта книга делится очень забавными и полезными рекомендациями, которые вы можете незамедлительно применить в своей работе. Программируя более десяти лет на разных языках и в разных командах, я хотел бы поделиться советами, хитростями и рекомендациями, которые очень помогли моей карьере в Swift, чего и вам желаю. Почему эта книга? Честно говоря, многие программы в этом мире работают на «некрасивом» коде, и это совершенно нормально. Если ваш продукт делает то, что нужно, это – нравится вам это или нет – вполне подойдет для бизнеса. Будучи разработчиком, вы должны убедиться, что ваш продукт работает, и работает хорошо. Но ваши пользователи не будут заглядывать под капот и указывать на страшных операторов if. Перфекционизм вреден для разработки программного обеспечения и является причиной большого количества незавершенных проектов.
Предисловие 17 Тем не менее существует большой разрыв между «Он делает то, что нужно» и проектом, в котором были приняты отличные решения, которые окупаются в долгосрочной перспективе. Работая над многочисленными проектами, я высоко ценю написание кода, который ваши коллеги и ваши будущие сотрудники будут четко понимать, потому что элегантный код означает меньше шансов на ошибки, повышенное удобство в обслуживании, лучшее понимание для разработчиков, которые наследуют код, море счастья для программистов и много других преимуществ. Другой аспект, который я ценю, – это надежность кода, то есть то, насколько стойкими к рефакторингу являются некоторые элементы. Сломается, если чихнуть на него? Или можно ли изменить код без хлопот? В этой книге я поделюсь своими советами, хитростями и рекомендациями, которые отлично подошли мне и компаниям, в которых я работал. Кроме того, она заполняет значительные пробелы в знаниях, которые могут возникнуть при работе со Swift. Хотя это книга о Swift, многие принципы, о которых здесь говорится, не ориентированы на Swift и также распространяются на другие языки программирования, потому что Swift заимствует множество идей и парадигм из других языков. После того как вы закончите читать книгу, вам, возможно, будет легко применять эти концепции в других языках. Например, вы узнаете много нового об опциона- лах или о том, как использовать метод reduce при работе с массивами. Позже вы можете решить изучать Kotlin, где можно сразу же применять опционалы и вышеуказанный метод, где он носит название fold. Вы также можете обнаружить, что Rust – и его аналогичные реализации обобщений – проще освоить. Из-за мультипарадигмальной природы Swift эта книга без предпочтения переключается между парадигмами объектно-ориентированного, функционального и протокольно-ориентированного программирования – хотя, по общему признанию, я все же предпочитаю другие методы, нежели создание подклассов. Переключение между этими парадигмами предлагает множество инструментов и решений проблемы, а также понимание того, почему определенное решение работает хорошо или нет. Если вы застряли в колее или открыты для множества новых идей программирования, эта книга ставит перед вами задачу решать проблемы различными способами. Подходит ли вам эта книга? Предполагается, что вы создали одно или несколько приложений на Swift. Вы работаете в команде? Еще лучше. Эта книга покажет вам, как написать хороший, понятный код, который будет оценен в командах, и поможет вам улучшить запросы на принятие изменений от других разработчиков. Ваш код будет более надежным и потребует меньше обслуживания от вас и вашей команды. Эта книга заполняет пробелы в знаниях как для новичков, так и для опытных разработчиков Swift. Возможно, вы освоили протоколы, но все еще боретесь с использованием метода flatMap при работе с типами или асинхронной обработкой ошибок. Или, может быть, вы создаете красивые приложения, но держитесь подальше от обобщений, потому что их трудно интерпретировать. Или, может быть, вы знаете, когда использовать структуру вместо класса, но не знаете, что перечисления иногда являются лучшей альтернативой. В любом случае, эта книга по-
Предисловие может вам с этими темами. К концу работа с обобщениями должна быть такой же естественной, как и в случае с циклами. Вы будете уверены в том, что будете вызывать метод flatMap для опционалов, будете знать, как работать с ассоциированными типами, и с радостью будете использовать метод reduce в своем повседневном труде при работе с итераторами. Если вы планируете в будущем пройти собеседование на должность программиста, чтобы получить новое место, вам понравится. Вы сможете ответить на множество важных вопросов, касающихся компромиссов и решений относительно разработки на языке Swift. Эта книга может даже помочь вам написать элегантный код в заданиях. Если вам просто нужно приложение из магазина приложений, продолжайте делать то, что делаете; нет необходимости читать эту книгу! Но если вы хотите написать более надежный, понятный код, который увеличивает ваши шансы получить место, преуспеть на работе или дать качественные комментарии по запросам на принятие изменений, вы попали в нужное место. Чем эта книга не является Эта книга ориентирована на Swift. В основном в ней используются примеры без фреймворков, потому что речь идет не об обучении Cocoa, iOS, Kitura или другим платформам и фреймворкам. В этой книге я часто пользуюсь Apple Foundation, чего трудно избежать, если вам нужны примеры из реальной жизни. Если вы работаете в Linux, то можете использовать swift.org, чтобы получить аналогичные результаты. Особый акцент на практических сценариях Эта книга очень практична и демонстрирует советы и приемы, которые вы можете сразу же применять при повседневном программировании. Не волнуйтесь: это не теоретическая книга. Вы узнаете много теории, но только благодаря использованию реальных проблем, с которыми рано или поздно сталкивается любой разработчик Swift. Тем не менее она не дотягивает до академического уровня, где обсуждается представление LLVM или машинный код. Кроме того, я позаботился о том, чтобы избежать своей личной любимой мозоли: я не делю подкласс «Animal» с «Dog» и не добавляю протокол «Flyable» в «Bird». Я также не добавляю «Foo» в «Bar». Вы будете иметь дело с реальными сценариями, такими как общение с API, загрузка локальных данных, рефакторинг и создание функций, и увидите полезные фрагменты кода, которые можно реализовать в своих проектах. Дорожная карта В следующих разделах представлен обзор книги, разделенный на главы. Книга довольно модульная, и вы можете начать с любой главы, которая вас интересует.
Предисловие 19 Некоторые главы я считаю важными. Глава 4 «Делаем опционалы второй натурой» является ключевой, потому что опционы очень распространены в Swift, и мы будем возвращаться к ним снова и снова в других главах. Чтобы понять абстрактную сторону Swift, я настоятельно рекомендую прочитать главу 7 «Обобщения», главу 8 «Становимся профессионалами в протокольно- ориентированном программировании» и главу 12 «Расширения протоколов». Эти главы закладывают прочную основу для ключевых навыков Swift. Обязательно прочтите их! В качестве бонуса, если вы заинтересованы в изучении методов функционального программирования, обратите внимание на главу 2 «Моделирование данных с помощью перечислений», главу 10 «map, flatMap и compactMap» и главу 11 «Асинхронная обработка ошибок с помощью типа Result». Глава 1: Введение Эта глава – своего рода разминка. В ней рассказывается о текущем состоянии Swift, о его положительных сторонах и недостатках и о том, чем мы будем заниматься в ходе прочтения данной книги. Она не очень техническая, однако подготовит вас к тому, о чем пойдет речь далее. Глава 2: Моделирование данных с помощью перечислений Эта глава отлично подойдет, если вы хотите напрячь свой мозг, по-другому взглянуть на моделирование данных и увидеть, насколько далеко могут зайти перечисления, чтобы помочь вам. Вы узнаете, как моделировать данные с помощью структур и перечислений и преобразовывать структуры в перечисления, и наоборот. Вам будет предложено отойти от обычного подхода к классам, подклассам и структурам и посмотреть, как вместо этого моделировать данные с помощью перечислений и зачем это нужно. Вы также познакомитесь с другими интересными способами использования перечислений и узнаете, как использовать их для написания более безопасного кода. К концу этой главы вы можете поймать себя на мысли, что пишете гораздо больше перечислений. Глава 3: Написание более чистых свойств Swift обладает богатой системой свойств со множеством опций на выбор. Вы научитесь выбирать правильный тип свойств для правильных типов ситуаций. Вы также создадите чистые вычисляемые свойства и хранимые свойства с поведением. Потом вы узнаете, когда использовать ленивые свойства, которые могут привес ти к незначительным ошибкам, если с ними обращаться неаккуратно. Глава 4: Делаем опционалы второй натурой Эта глава не оставит камня на камне касательно опциональных типов.
Доступ онлайн
В корзину