Что такое диспетчеризация (dispatch) в Swift и как она работает
Что проверяют
Понимаете ли вы, как компилятор решает, какой код вызвать, и почему от этого зависит и производительность, и поведение при наследовании.
Как отвечать
Диспетчеризация это выбор реализации метода при вызове. В Swift их три вида.
Статическая (прямая). Адрес известен на этапе компиляции, вызов идёт напрямую, возможна подстановка тела. Так вызываются методы структур и перечислений, final и private методы классов, методы в расширениях протоколов, не объявленные в самом протоколе.
Через таблицу (witness table и vtable). У классов вызовы идут через таблицу методов: компилятор берёт адрес из неё в рантайме. Так работает переопределение методов в наследниках. У протоколов аналогично, через таблицу соответствий.
Динамическая через Objective-C. Методы, помеченные @objc dynamic, и всё, что наследуется от NSObject, вызываются через objc_msgSend с поиском по селектору. Медленнее всего, зато допускает подмену реализации в рантайме, на чём построены KVO и swizzling.
Практическое следствие: final и private не просто про инкапсуляцию, они позволяют компилятору перейти к прямому вызову. В структурах диспетчеризация статическая по умолчанию, поэтому они быстрее классов в горячем коде.
Ловушка, которую любят спрашивать: метод, объявленный только в расширении протокола, диспетчеризуется статически по типу переменной, а не по фактическому типу объекта. Из-за этого один и тот же объект под разными типами даёт разное поведение.
Где спотыкаются
Не различают расширение протокола и требование протокола: первое статическое, второе через таблицу.
Считают dynamic синонимом «динамический вызов в Swift». Это про среду выполнения Objective-C и работает не везде, например на Linux.
Забывают, что обобщённый код может специализироваться компилятором, и тогда вызов становится прямым.