Какие проблемы решает ключевое слово final в рамках диспетчеризации в Swift
Что проверяют
Знаете ли вы, какие виды диспетчеризации есть в Swift и какую компилятор выбирает для метода класса по умолчанию. Следом обычно спрашивают, нужен ли final при включённой Whole Module Optimization и как ведут себя методы в расширениях протоколов.
Как отвечать
Опишите три механизма:
- статическая (direct): адрес функции известен на этапе компиляции. Так вызываются методы структур, перечислений,
final-членов иprivate-методов; - табличная: у класса есть таблица виртуальных методов (vtable), вызов идёт через неё, потому что наследник мог переопределить метод. Для протоколов аналог это witness table;
- сообщения:
@objc dynamicуходит вobjc_msgSend. Это самый медленный путь, зато на нём работают KVO и swizzling.
final на классе или члене класса говорит компилятору, что переопределения не будет. Он вызывает метод напрямую, а значит может его встроить (inline) и оптимизировать дальше. Выигрыш заметен в горячих циклах, в обычном UI-коде его почти не видно.
Честно добавьте про WMO: в Release-сборке компилятор видит модуль целиком и сам выводит финальность для internal и private членов без наследников. Явный final при этом не бесполезен:
- намерение: класс закрыт для наследования, и это видно при чтении;
Sendable: класс без изоляции к актору проходит проверку наSendable, только если онfinalи хранит лишь неизменяемыеSendable-свойства. В строгом режиме Swift 6 это важно;- инициализаторы протоколов: если протокол требует
init, финальному классу не нужен модификаторrequired.
Где спотыкаются
Называют final главным способом ускорить приложение. Без профилирования в Instruments это оптимизация наугад, а WMO и так делает большую часть работы.
Путаются с методами в расширении протокола. Метод, которого нет в требованиях протокола, диспетчеризуется статически: через переменную с типом протокола вызовется реализация из расширения, а не из класса.
Считают, что final запрещает расширения. extension к финальному классу писать можно, запрещены только наследование и переопределение.