В чем разница между статическим (Static Dispatch) и динамическим (Dynamic Dispatch) в Swift?

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

Ответ

Динамическая диспетчеризация (Dynamic Dispatch) — механизм, при котором решение о том, какую реализацию метода вызвать, принимается во время выполнения программы. Это основа полиморфизма.

  • Как работает: Используется таблица виртуальных методов (vtable) для классов или таблица witnes для протоколов.
  • Где используется: Для методов в не-final классах и требований протоколов.
  • Плюсы: Гибкость, поддержка наследования и полиморфизма.
  • Минусы: Небольшие накладные расходы на поиск реализации.

Статическая диспетчеризация (Static Dispatch) — решение о вызове метода принимается на этапе компиляции.

  • Как работает: Компилятор напрямую подставляет адрес функции.
  • Где используется: Для структур, перечислений, final-методов, private-методов и расширений протоколов с реализацией по умолчанию (не переопределённых).
  • Плюсы: Максимальная производительность, возможность агрессивной оптимизации (inlining).
  • Минусы: Отсутствие полиморфного поведения.

Пример:

class Animal {
    // Dynamic dispatch (можно переопределить)
    func makeSound() { print("...") }
    // Static dispatch (нельзя переопределить)
    final func breathe() { print("Breathing") }
}

class Dog: Animal {
    override func makeSound() { print("Woof!") } // Переопределение
}

let myPet: Animal = Dog()
myPet.makeSound() // "Woof!" (Dynamic Dispatch: решение в runtime)
myPet.breathe()   // "Breathing" (Static Dispatch: решение в compile time)

Оптимизация: Используйте final, private и протоколы с реализацией по умолчанию для увеличения доли статической диспетчеризации и повышения производительности.