Что такое обобщения (Generics) в Swift и для чего они нужны?

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

Ответ

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

Основная цель: Устранить дублирование кода за счет абстрагирования от конкретных типов данных.

Пример 1: Обобщенная функция

// Функция меняет местами значения ЛЮБОГО одного типа.
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var int1 = 10, int2 = 20
swapTwoValues(&int1, &int2) // T выводится как Int

var string1 = "hello", string2 = "world"
swapTwoValues(&string1, &string2) // T выводится как String

Пример 2: Обобщенный тип (Generic Type)

// Стек, который может хранить элементы ЛЮБОГО одного типа.
struct Stack<Element> {
    private var items: [Element] = []

    mutating func push(_ item: Element) {
        items.append(item)
    }

    mutating func pop() -> Element? {
        return items.popLast()
    }
}

var intStack = Stack<Int>()
intStack.push(5)

var stringStack = Stack<String>()
stringStack.push("Swift")

Ключевые преимущества:

  1. Type Safety: Компилятор следит за корректностью типов, ошибка intStack.push("text") будет поймана на этапе компиляции.
  2. Устранение дублирования: Не нужно писать отдельные функции swapInts, swapStrings и т.д.
  3. Оптимизация: Код с дженериками компилируется в нативный код для конкретных типов, минимизируя накладные расходы времени выполнения.

Где используются повсеместно:

  • Стандартные коллекции: Array<Element>, Dictionary<Key, Value>.
  • Опциональные типы: Optional<Wrapped> (это Wrapped?).
  • Асинхронные API: Future<Output, Failure> в Combine, Task<Success, Failure> в Concurrency.