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

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

Ответ

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

  1. Статическая (Static Dispatch)

    • Решение принимается на этапе компиляции.
    • Используется для: обычных функций, struct/enum методов, final методов и классов, private методов.
    • Пример:
      struct Calculator {
          func add(_ a: Int, _ b: Int) -> Int { a + b } // Статическая диспетчеризация
      }
  2. Диспетчеризация через таблицу свидетельств (Protocol Witness Table Dispatch)

    • Используется для методов протоколов и обобщенных (generic) контекстов.
    • Реализация выбирается в runtime на основе конкретного типа, соответствующего протоколу.
    • Пример:
      protocol Drawable { func draw() }
      struct Circle: Drawable { func draw() { print("Drawing circle") } }
      let shape: Drawable = Circle()
      shape.draw() // Вызов через PWT
  3. Динамическая диспетчеризация (Virtual Table Dispatch)

    • Классический ООП-подход для нефинальных (non-final) классов.
    • Решение принимается в runtime на основе типа объекта.
    • Пример:
      class Animal { func makeSound() { print("...") } }
      class Dog: Animal { override func makeSound() { print("Woof!") } }
      let pet: Animal = Dog()
      pet.makeSound() // Вызов через v-table -> "Woof!"
  4. Диспетчеризация сообщений (Objective-C Message Dispatch)

    • Полностью динамическая, используется только для элементов, помеченных @objc и dynamic.
    • Позволяет делать method swizzling и отвечает на responds(to:).
    • Пример:
      class ObjCClass: NSObject {
          @objc dynamic func message() { print("Dynamic message") }
      }