[БЕЗ_ЗВУКА] Приветствую. В этой лекции мы поговорим о том, как в Swift проверять и приводить типы. Приведение типов используется, если необходимо рассматривать объект как его сабкласс или родительский класс. Изменение типа на произвольный не имеет смысла, так как всегда будет заканчиваться неудачей. Рассмотрим иерархию классов. Есть базовый класс для хранения имени устройства. От него наследуются классы, содержащие информацию о телефоне и наушниках. Они добавляют по одному полю. Также объявлена функция, выводящая информацию о девайсе. На вход она принимает родительский класс Device. В эту функцию можно передать устройство или любой его сабкласс. Для этого выполняется неявное приведение типа. Оно выполняется только от более детализированного типа к менее детализированному. Например, от класса к его родительскому классу или от структуры к протоколу, который она поддерживает. Если бы функция принимала на вход телефон, то передать в нее базовые устройства было бы нельзя. Компилятор выдаст ошибку о невозможности конвертации типов. Мы можем положить наши объекты в массив. При этом тип массива будет Device. Если мы возьмем объект из массива по индексу, то его тип тоже будет Device. Но мы можем проверить, является ли какой-то объект сабклассом определенного типа. Для этого используется оператор is, он возвращает результат проверки в виде bool. Мы можем воспользоваться этим оператором, например, для того чтобы найти первый телефон в нашем массиве. Результат будет иметь тип Optional Device, так как функция first может вернуть nil, если элемент не найден. Оператор is не поможет нам обратиться к свойству Capacity полученного объекта, так как он просто осуществляет проверку. Для этого нам нужно явно привести объект к сабклассу. Такая операция называется Downcasting. В Swift для этого используются операторы as с вопросительным знаком и as с восклицательным знаком. As с вопросительным знаком возвращает опциональный тип. Если операция преобразования будет завершена с ошибкой, то результат будет nil. В примере на слайдах объект типа Phone приводится к Headphones. Так как он не является его сабклассом, то такое преобразование невозможно. As с восклицательным знаком, напротив, возвращает именно тот тип, котрый мы указали. Использовать его можно, только если вы уверены, что результат будет успешен, иначе ваше приложение завершится с ошибкой. Принудительного преобразования лучше избегать. Вместо него можно воспользоваться конструкцией if let для проверки значения. Рассмотрим пример. Допустим, нужно выводить разное описание для каждого сабкласса Device. Для этого необходимо привести тип и вывести значение полей. Теперь для каждого типа выводится свое описание. При этом, никаких ошибок произойти не может. Также в Swift есть простой оператор as. Его использование ограничено ситуациями, когда уже на этапе компиляции известно, что результат будет успешным. Например, при преобразовании типа вверх по иерархии классов или при взаимодействии с некоторыми типами Objective-C. Рассмотрим оба случая. Первый называется Upcasting. В большинстве случаев Swift сам выполняет такое преобразование, однако оператор as может оказаться полезным в случае неоднозначностей. На слайдах вы видите две функции с одинаковым названием, но разными типами. Swift сам вызовет нужную, исходя из типа аргумента. Так как передаваемый объект имеет тип phone, то вызовется соответствующая функция. Однако в некоторых случаях нам нужно изменить это поведение. Для этого можно воспользоваться оператором as, так как результат преобразования не может быть nil. Второй пример использования этого оператора — это бриджинг между типами Swift и Objective-C. Бриджинг — это автоматическое преобразование типов. Вы можете ознакомиться со списком типов, поддерживающих эту возможность, по ссылке в материалах к лекции. Мы рассмотрим работу со строками. Для того чтобы присвоить строку к NSString нужно просто указать этот тип после оператора as. То же самое действует и в обратную сторону. Преобразование типов в некоторых случаях необходимо. Разрабатывая приложение, вы обязательно с ним столкнетесь, однако если вам приходится использовать, задумайтесь, возможно, есть другой способ выполнить задачу и не завязываться на тип данных. Давайте рассмотрим, как можно переделать функцию, выводящую разное описание для каждого типа, чтобы все было в стилистике Swift. Объявим протокол. Его будут реализовывать все объекты, информацию о которых нужно выводить. Так как через расширение нельзя переопределять методы в сабклассах, придется переделать первоначальное объявление классов. Функция printDetailedDescription будет принимать объект типа printable и просто выводить результат выполнения метода, описанного в протоколе. Теперь можно передавать функцию, любой printable тип. При этом мы избежали не очень красивой проверки типа. Функция printDetailedDescription стала зависеть только от абстрактного протокола и не знает деталей реализации других типов. Таким образом, обеспечивается слабое сцепление классов. Благодаря тому, что использовались протоколы, а не обычные наследования, мы легко можем передать в эту функцию любой тип, в том числе не сабкласс Device. В примере поддержка Printable добавлена в системный класс UIView, в котором для формирования описания используется стандартный метод Description. На этом лекция по проверке типов подходит к завершению. Мы рассмотрели, как можно проверить и приводить типы в Swift. Также мы затронули тему взаимодействия Swift и Objective-C, но более подробно об этом мы расскажем на следующих курсах.