В чем разница протоколов и наследования и как использовать композицию протоколов
Что проверяют
Понимаете ли вы, почему Swift называют протокол-ориентированным языком и когда наследование классов всё ещё оправдано. Следом часто просят функцию, принимающую объект с двумя протоколами сразу, и спрашивают про диспетчеризацию методов из расширений.
Как отвечать
Начните с различий:
- наследование: только для классов и только от одного родителя. Потомок получает хранимые свойства и реализацию, может делать
overrideи зватьsuper. Цена в жёсткой связи: изменение базового класса ломает наследников, а вместе с классом приходит ссылочная семантика; - протоколы: контракт, который могут принять
struct,enum,classиactor. Тип соответствует любому числу протоколов, реализацию по умолчанию дают расширения протокола. Хранимых свойств протокол не добавляет; - композиция протоколов: объединение требований прямо в месте использования через
&, без нового именованного протокола. Например,func save(_ item: some Identifiable & Codable)илиvar delegate: (any Loadable & Refreshable)?. СамCodableв стандартной библиотеке объявлен какtypealias Codable = Decodable & Encodable.
Добавьте разницу между some и any: some означает конкретный тип, известный компилятору, без накладных расходов, а any это экзистенциальный контейнер с динамической диспетчеризацией.
Наследование остаётся нормальным выбором там, где его диктует фреймворк: подклассы UIView и UIViewController. Для собственных моделей и сервисов обычно берут протоколы и структуры.
Где спотыкаются
Называют композицией protocol Bird: Flyable, Swimmable {}. Это наследование протоколов, то есть новый именованный тип. Композиция делается через & и нового протокола не создаёт.
Не знают про статическую диспетчеризацию. Метод, объявленный только в расширении протокола, а не в самом протоколе, вызывается по статическому типу: переменная типа any P вызовет реализацию из расширения, даже если у конкретного типа есть своя.
Говорят, что протоколы дают множественное наследование. Они дают множественное соответствие контрактам, но не наследование состояния: хранимое свойство в расширении протокола объявить нельзя.