Книга: Swift. Основы разработки приложений под iOS, iPadOS и macOS. 5-е изд. дополненное и переработанное
Назад: 6. Кортежи (Tuple)
Дальше: 8. Диапазоны (Range)

7. Последовательности и коллекции

Как и в любом языке программирования, в Swift есть механизмы агрегации произвольных значений для манипуляции ими как единым значением. С первым и самым простым из них (кортежи) вы познакомились в предыдущей главе. Помимо кортежей, Swift позволяет использовать последовательности и коллекции, знакомству с которыми будут посвящены несколько последующих глав.

7.1. Классификация понятий

В нашем физическом мире все может быть классифицировано и подробно описано, «разложено по полочкам». Для любого объекта можно выделить свойства и найти признаки, по которым он будет связан с другими объектами или объединен с ними в группы.

Предположим, что мы хотим классифицировать группу физических объектов «автомобили». Автомобиль — это техническое средство, обладающее в самом упрощенном виде двигателем и колесами. Автомобиль — это наивысшее понятие в рассматриваемой области знаний. Любая конкретная модель авто обладает описанными свойствами (двигателем и колесами), то есть относится к категории «Автомобили» (рис. 7.1).

Рис. 7.1. Классификация автомобилей

Но конечно же, на этом классификация не заканчивается. Мы можем выделить еще ряд характеристик, которые позволят разбить главную категорию на подкатегории. К примеру, по используемому источнику энергии их можно разделить на авто с электродвигателями и с двигателями внутреннего сгорания. В этом случае конкретные модели могут быть распределены уже по данным подкатегориям (рис. 7.2).

Рис. 7.2. Классификация автомобилей

Каждая категория может быть описана подкатегориями по различным свойствам, а каждая конкретная реализация может входить в различные категории (рис. 7.3).

Рис. 7.3. Классификация автомобилей

Категории по своей сути — это всего лишь наборы требований. Они не описывают, как эти требования должны быть реализованы. Категория «Автомобили» требует наличия двигателя и колес, но не дает никаких рекомендаций по их конкретной реализации.

Такие наборы требований (категории) в Swift называются протоколами (а в некоторых других языках программирования вы могли встретить понятие интерфейса). В будущем мы подробно изучим все возможности протоколов, а также научимся самостоятельно их создавать и использовать.

Если категория — это набор требований, то порядок их реализации в реальном мире описывается в стандарте. Именно стандарт определяет, что и как должно функционировать. Стандарты в Swift реализованы в виде типов данных. Да-да, тех самых типов данных, с которыми мы знакомимся в течение уже нескольких глав. Любой тип данных может реализовывать множество протоколов, а может и не реализовывать их вовсе.

В результате реализации стандарта создается конечное изделие со своими уникальными характеристиками. К примеру, для нескольких одинаковых автомобилей, выполненных по конкретным чертежам (стандартам), уникальным будет VIN.

Конкретная реализация типа данных в Swift называется объектом, или экземпляром (это синонимы, но Apple рекомендует использовать второе понятие). В будущем мы еще неоднократно вернемся к данному вопросу, несколько раз подробно разобрав его.

В табл. 7.1 показано соответствие понятий реального мира и мира Swift, а также несколько примеров. Начните ее изучение с двух центральных столбцов.

Таблица 7.1. Соответствие понятий

Пример из реального мира

Понятия реального мира

Понятия в Swift

Пример из Swift

Автомобили с бензиновым двигателем

Категория

Протокол

SignedNumber (требует, чтобы тип данных обеспечивал хранение как положительных, так и отрицательных чисел)

Kia Rio

Стандарт (модель)

Тип данных

Int

Kia Rio VIN XW122FX849

Конкретная реализация

Экземпляр

2 (целое число типа Int)

Протокол Тип данных Экземпляр — это типовой вариант реализации функционала в Swift, но это относится к методологиям объектно-ориентированного и протокол-ориентированного программирования, которые будут рассмотрены в дальнейшем.

Кстати, ранее вы уже познакомились с несколькими протоколами, но тогда они были названы категориями. Помните о Hashable, Comparable и Equatable? Все это протоколы, содержащие требования к функционалу типов данных.

ПРИМЕЧАНИЕ Думаю, вы заметили, что материал книги постепенно усложняется. Уверен, что многие из вас не поймут все и сразу, так как для закрепления изу­ченного требуется практика, много практики. Продолжайте обучение, и в нужный момент лампочка над головой загорится, когда все начнет складываться в единую картину.

Но в любом случае все, о чем я говорю, — это очень важно! Вам необходимо читать, перечитывать и вчитываться, стараясь получить из описания максимум полезной информации.

7.2. Последовательности (Sequence)

Представьте, что на вашем столе лежат разноцветные шарики. Так как они мешают изучению Swift (рука постоянно тянется потрогать их), вы решаете убрать надоедливые предметы в специальный цилиндрический кейс, где они располагаются один на другом. При этом вы можете видеть только верхний шарик. Для того чтобы добраться к нижнему, вам потребуется достать все предыдущие. Такой порядок группировки элементов в Swift называется последовательностью.

Последовательность (Sequence) — набор элементов, выстроенных в очередь, в котором есть возможность осуществлять последовательный (поочередный) доступ к ним. При этом не предусмотрен механизм, позволяющий обратиться к какому-либо определенному элементу. Вы, как было сказано выше, можете лишь последовательно перебирать элементы последовательности.

Sequence — это название протокола в Swift, который определяет требования к последовательностям. Если какой-либо тип данных принимает к реализации протокол (выполняет его требования), то значение этого типа (экземпляр) можно назвать последовательностью. Протокол Sequence требует, чтобы тип данных обеспечивал хранение множества однотипных значений и организовывал последовательный доступ к ним с помощью последовательного перебора.

Вернемся к примеру с шариками. Перед вами возникла задача определить, есть ли среди них зеленый. Вы смотрите на верхний шарик и понимаете, что он красный. Достаете его и видите желтый. Достаете его и видите нужный зеленый.

Говоря языком программирования, некий виртуальный указатель в исходном состоянии направлен на первый шарик. Проведя его анализ (определив цвет), указатель переходит к следующему шарику и анализирует. И так далее (рис. 7.4).

Рис. 7.4. Поиск элемента коллекции

Последовательности могут быть конечными и бесконечными. К примеру, последовательность Фибоначчи (каждое последующее значение — это сумма двух предыдущих) является бесконечной. Программа может перебирать элементы, но ее конец никогда не будет достигнут.

С примерами типов данных, реализующих требования последовательностей, мы познакомимся немного позже.

7.3. Коллекции (Collection)

Последовательности предъявляют довольно ограниченные требования к типам данных, реализующим их. Среди этих требований нет необходимости реализации механизма прямого доступа к произвольному элементу. К примеру, если тип данных является последовательностью, то для доступа к необходимому элементу требуется организовать поочередный доступ ко всем предыдущим элементам. Для решения проблемы прямого доступа к элементу Swift позволяет использовать коллекции.

Коллекция (Collection) — это последовательность (Sequence), в которой можно обращаться к отдельному элементу напрямую. Другими словами, Collection — это протокол, основанный на протоколе Sequence, который при этом имеет дополнительное требование по обеспечению прямого доступа к элементам. Помимо этого, коллекция не может быть бесконечной (в отличие от Sequence).

Для доступа к элементам коллекции используются индексы (indicies). Они могут быть представлены как в виде обычного числового значения (порядковый номер элемента), так и в виде более сложных структур (как, например, в словарях или строках, но об этом поговорим позже).

На рис. 7.5 приведена упрощенная схема классификации рассмотренных протоколов и их требований.

Рис. 7.5. Классификация протоколов и их требования

В будущем вы научитесь создавать собственные типы данных, основанные на последовательностях и коллекциях. А сейчас необходимо уделить особое внимание информации, находящейся в этой части книги, так как приведенный материал достаточно важен и будет регулярно использоваться в будущем.

7.4. Работа с документацией

Если у вас возникают вопросы при изучении материала, это говорит о том, что обучение идет правильно. Если какой-то материал оказывается для вас сложным и необъятным, это также хороший знак, так как у вас появляется стимул самостоятельно искать ответы на поставленные вопросы и разбираться с проблемными моментами. ­Изучение языка само по себе не дает навыков разработки приложений. Для этого требуется изучить большое количество дополнительного материала, а самое важное — необходимо научиться работать с официальной документацией, с помощью которой вы сможете ответить на большинство возникающих вопросов.

Swift имеет большое количество разнообразных типов, но все они описаны в документации. Ранее мы говорили с вами, что типы могут быть разделены на категории в соответствии с реализуемым ими функционалом (реализуемыми протоколами).

Предлагаю на примере разобраться с одним утверждением, о котором мы говорили ранее. Это поможет вам лучше воспринимать материал, которому посвящена данная часть книги.

Утверждение: «Все фундаментальные типы являются хешируемыми».

Напомню, что хешируемым называется такой тип данных, для значений которого может быть высчитан специальный числовой хеш, доступ к которому может быть получен через свойство hashValue. Если тип называется хешируемым, значит, он соответствует протоколу Hashable.

Выделим из данного утверждения частный случай: «Тип данных Int является хешируемым, то есть соответствует протоколу Hashable».

В Xcode Playground напишите код из листинга 7.1.

Листинг 7.1

var intVar = 12

В данном примере создается переменная целочисленного типа со значением 12. Зажмите клавишу Opt и щелкните по имени переменной, после чего отобразится информационное окно, содержащее сведения об имени, типе переменной и месте ее объявления (рис. 7.6).

Рис. 7.6. Всплывающее информационное окно

Если щелкнуть по имени типа данных (Int), то откроется новое окно, содержащее справочную документацию (рис. 7.7).

Рис. 7.7. Окно со справочной документацией

Здесь вы можете ознакомиться с описанием типа данных, а также его методов и свойств.

ПРИМЕЧАНИЕ Для работы с документацией необходимо знание английского языка! И к сожалению, ситуация вряд ли изменится. Отечественные разработчики не спешат создавать новые интересные учебные материалы, а зачастую ограничиваются лишь переводом зарубежных статей.

Если у вас возникают трудности с чтением англоязычных статей, то самое время начать исправлять ситуацию. В любом случае ваша карьера во многом зависит от знания языка, каждая вторая фирма «выкатывает» это требование в описании вакансии.

Я считаю, что необязательно тратить тысячи рублей ежемесячно на занятия с преподавателем (особенно если у вас уже есть школьный или институтский опыт изу­чения). Лично я изучаю и поддерживаю уровень языка с помощью следующих средств:

• Мобильные приложения. Duolingo для словарного запаса, Simpler и «Полиглот» для повторения грамматики (плюс в Simpler потрясающие детективные истории помогают учиться слушать иностранную речь), Lingualeo для чтения небольших несложных рассказов и тематических статей. Так можно с пользой проводить 20–30 минут дороги в общественном транспорте.

• Адаптированные книги. Вы можете купить, к примеру, «Тома Сойера» или «Алису в Стране чудес», но адаптированную для чтения новичками. Самое важное, что есть возможность выбора книг в соответствии с уровнем знания языка. К некоторым изданиям также идут аудиоматериалы (тренировка восприятия речи на слух).

• Учебные видео на Youtube. Тот же «Полиглот» будет очень полезен для начинающих.

• Общение с носителями языка по Skype. Для этого существует большое количество сервисов, где вы можете найти себе партнера для бесед (в большинстве случаев это платные услуги).

• Просмотр фильмов с оригинальной дорожкой. Именно это всегда было целью изучения мной английского языка!

Но возможно, для вас правильным является именно обучение с преподавателем. Самое важное в этом деле — не бояться пробовать, не бояться ошибок! И очень советую — как можно раньше начинайте слушать речь: песни, фильмы с субтитрами и т.д., так как знание языка не должно оканчиваться на умении читать.

Если перейти в самый конец страницы описания типа Int, то там вы найдете раздел Comfort To, в котором как раз и описаны протоколы, которым соответствует данный тип (рис. 7.8). Среди них вы найдете и упомянутый выше Hashable.

Рис. 7.8. Протоколы типа данных Int

Обратите внимание, что в данном списке отсутствуют протоколы Comparable и Equatable, хотя ранее говорилось, что Int, как и другие фундаментальные типы, соответствует и им. С этим мы разберемся немного позже.

Если щелкнуть по имени протокола Hashable, то произойдет переход к его описанию. В данном случае описание куда более подробное, нежели у Int. При желании вы можете ознакомиться с ним.

В разделе Adopted By перечислены все типы данных, которые соответствуют данному протоколу. Обратите внимание на раздел Inherits From, в нем указан уже известный нам протокол Equatable. В этом разделе перечисляются протоколы, которые являются родительскими по отношению к данному. Таким образом, если какой-то тип данных соответствует требованиям протокола Hashable, то это значит, что он автоматически соответствует требованиям протокола Equatable. Так происходит и с типом Int (помните, выше у данного типа в разделе Comforts To отсутствовала ссылка на Equatable?). Исходя из этого можно сказать, что протоколы могут быть в отношениях «отец–сын».

Но все еще остается неясным, каким образом тип Int относится к протоколу Comparable. Если провести небольшой анализ и выстроить всю цепочку зависимостей, то все встанет на свои места (рис. 7.9).

Рис. 7.9. Порядок следования протоколов в типе Int

Таким образом, тип Int выполняет требования протокола Comparable через линейку протоколов SignedInteger, BinaryInteger и Strideable. Каждый дочерний протокол (сын) выполняет требования отца, но также накладывает дополнительные требования.

Но что такое реализация протокола? Что значит, если тип выполняет его требования? Как выполняются эти требования? Обо всем этом вы узнаете в будущих главах книги.

Работая с документацией, вы сможете найти ответы практически на любые вопросы, связанные с разработкой. Не бойтесь искать необходимые материалы, это может значительно улучшить качество вашего обучения.

ПРИМЕЧАНИЕ Вы можете в любой момент открыть окно документации с помощью пункта Developer Documentation в разделе Help главного меню Xcode.

Назад: 6. Кортежи (Tuple)
Дальше: 8. Диапазоны (Range)