Вся статья - это конспект видео с ютуба "Method Dispatch - Диспетчеризация методов в Swift", пишу для себя, так лучше запоминаю
Диспетчеризация - это процесс выбора имплементации метода при его вызове.
Виды диспетчеризации:
- Static/Direct_ (статичная/прямая)
- Table (табличная)
- Witness-table
- Virtual-table
- Messages (на сообщениях) - Obj-C
Static/Direct_ - прямой вызов метода уже известный на этапе компиляции. То есть метод располагается где-то в памяти, при его вызове извлекается ссылка на этот метод, и начинается его выполнения
+ Самый быстрый тип диспетчеризации (0-2 ns)
- Не реализует полиморфизм и наследование
Table (табличная)
1) Witness-table - (про протоколы)
+ Медленее, чем Static/Direct_ (~3 ns)
+ Реализует полиморфизм
- Не реализует наследование
Если класс реализует несколько протоколов, то для каждой такой реализации будет своя Witness-таблица.
2) Virtual-table- (про классы)
+ Медленее, чем Static/Direct_ (~3 ns)
+ Реализует полиморфизм
+ Реализует наследование
Как видно method1 не изменился и ссылка у таблицы Child и Parent совпадают
Messages
+ KVC/KVO
+ Поддержка Swizzling методов
- Самый медленный ~ 5.82ns
В swift используется только для совместимости с obj-c runtime
Работает в Runtime
Value type
Для всех value type для функций, если они не по реализации протокола, используется direct_ dispatch.
Reference type
В обычном случае из-за того, что Reference type поддерживает наследование, то используется Virtual-table
Reference type + Extensions
Вообще для всех extensions и для протоколов, структур и классов используется direct dispatch, кроме расширений для NSObject
Пограничная ситуация
Witness Table во втором случае, потому что кастим к протоколу и в основном тела протокола функция находится не в extension, в противном случае (то есть в extension) было бы то же Direct.
Так для класса, который помечен как final, используется прямая диспетчеризация - Direct dispatch, потому что final делается класс не наследуемым и соответственно не допускает полиморфизм
Обобщение