Есть ли ограничения на количество протоколов, которые можно подключить к классу в Swift
Что проверяют
Вопрос с подвохом: ограничения в языке нет, и интервьюер смотрит, не начнёте ли вы его выдумывать. Настоящая тема дальше: как устроены протоколы, где возникает динамическая диспетчеризация и что делать, когда требования двух протоколов пересекаются.
Как отвечать
Коротко: класс наследуется максимум от одного суперкласса, а протоколов может принять сколько угодно. Суперкласс в списке идёт первым: class ProfileVC: UIViewController, UITableViewDataSource, UITableViewDelegate. У struct и enum наследования нет, а протоколов тоже сколько угодно.
Дальше то, что показывает уровень:
- композиция протоколов:
A & Bв типе параметра без объявления нового протокола. Стандартный примерtypealias Codable = Decodable & Encodable; - соответствие в расширениях: идиоматично выносить каждый протокол в свой
extension, так класс читается по частям; - производительность: число протоколов на скорость вызовов не влияет. Цена появляется при работе через экзистенциал
any P: вызов идёт через witness table, значение упаковывается в экзистенциальный контейнер. Дженерики иsome Pдают компилятору специализировать код. С Swift 5.6anyпишется явно, а флагExistentialAnyделает это обязательным; - пересечения: если два протокола требуют метод с одной сигнатурой, одна реализация закрывает оба. Одноимённый ассоциированный тип у типа будет один на оба протокола, развести их нельзя;
- ограничители:
AnyObjectдля протоколов только под классы,@objcдля опциональных требований.
Если протоколов у класса очень много, это сигнал про архитектуру, а не про язык: у типа слишком много обязанностей, и часть стоит отдать отдельным объектам.
Где спотыкаются
Говорят, что много протоколов замедляют приложение. Замедляет способ использования, а не количество.
Не знают про статическую диспетчеризацию методов из расширения протокола. Метод, объявленный только в extension и не входящий в требования, выбирается по статическому типу, и через any P переопределение в классе не вызовется.
Путают принятие нескольких протоколов с множественным наследованием классов и говорят, что Swift его поддерживает.