Какие типы диспетчеризации методов (Message Dispatch) существуют в Swift?

«Какие типы диспетчеризации методов (Message Dispatch) существуют в Swift?» — вопрос из категории Swift Core, который задают на 22% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Диспетчеризация методов (Dispatch) — это механизм определения того, какая реализация метода должна быть выполнена при его вызове. Swift использует несколько стратегий, балансируя между производительностью и гибкостью.

1. Direct Dispatch (Статическая диспетчеризация)

  • Как работает: Адрес функции определяется на этапе компиляции. Вызов происходит напрямую, без поиска.
  • Производительность: Самый быстрый вариант (минимальные накладные расходы).
  • Используется для:
    • struct и enum (все методы по умолчанию).
    • final методы и классы.
    • static методы.
    • Методы, объявленные с модификатором private или fileprivate (где полиморфизм невозможен).
      struct MyStruct {
      func doWork() { } // Direct Dispatch
      }
      final class FinalClass {
      func doWork() { } // Direct Dispatch
      }

2. Table Dispatch (Диспетчеризация через таблицу)

  • Как работает: Каждый класс имеет виртуальную таблицу (vtable) с указателями на реализации своих методов. Вызов — это обращение по индексу в этой таблице.
  • Производительность: Немного медленнее прямого вызова (две дополнительные операции чтения из памяти).
  • Используется для: Нефинальных (non-final) методов в классах по умолчанию.
    class BaseClass {
    func doWork() { } // Table Dispatch (если класс не final)
    }
    class ChildClass: BaseClass {
    override func doWork() { } // Свой слот в vtable
    }
    let object: BaseClass = ChildClass()
    object.doWork() // Вызовется ChildClass.doWork через vtable

3. Message Dispatch (Динамическая диспетчеризация)

  • Как работает: Использует механизм рантайма Objective-C. При вызове метода отправляется сообщение (message), и рантайм ищет подходящую реализацию в иерархии классов (может включая категории). Поддерживает method swizzling.
  • Производительность: Самый медленный вариант из-за динамического поиска.
  • Используется в Swift для:
    • Методов и классов, помеченных @objc.
    • Методов с модификатором dynamic.
    • Наследования от NSObject и вызовов через KVO.
      class MyClass: NSObject {
      @objc dynamic func doWork() { } // Message Dispatch
      }

Почему это важно? Выбор стратегии влияет на производительность и возможности. Swift по умолчанию стремится к Direct/Table Dispatch для скорости, но предоставляет Message Dispatch для совместимости с Objective-C и крайних случаев динамического поведения.