Вопрос проверяет понимание оптимизации вызовов методов и влияние ключевого слова final на производительность.
Объявление класса или метода как final запрещает наследование или переопределение, что позволяет компилятору использовать статическую (direct) диспетчеризацию вместо динамической. Это убирает накладные расходы виртуальных вызовов и ускоряет исполнение.
Динамическая vs статическая диспетчеризация:
Динамическая: метод выбирается во время выполнения (виртуальный вызов).
Статическая: метод разрешается на этапе компиляции (прямой вызов).
Роль final:
final class запрещает наследование.
final func запрещает переопределение в подклассах.
Компилятор уверен в конкретном типе и может убрать виртуальную таблицу (vtable) для таких методов.
Пример:
final class Logger {
func log(_ msg: String) { print(msg) }
}
// вызов Logger().log("Hello") — прямой, без lookup в vtableКогда применять:
Для утилитарных классов и финальных точек расширения API.
Когда требуется максимальная производительность в горячих путях.
Вывод:final улучшает производительность за счёт перехода от динамической к статической диспетчеризации и уменьшения накладных расходов на виртуальные вызовы.