Generics — это мощный механизм в Swift, позволяющий писать гибкий и переиспользуемый код, который может работать с разными типами данных, сохраняя при этом строгую типизацию.
Generics позволяют создавать функции, структуры, классы и перечисления, которые могут работать с любым типом, а не только с конкретным (например, Int
, String
и т. д.).
Представьте, что вам нужна функция, которая меняет местами два значения. Без Generics пришлось бы писать отдельные функции для каждого типа:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temp = a
a = b
b = temp
}
Это неэффективно и нарушает принцип DRY (Don't Repeat Yourself).
С Generics можно написать одну универсальную функцию:
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
Теперь функция работает с любым типом T
:
var a = 5, b = 10
swapTwoValues(&a, &b) // Работает с Int
var x = "Hello", y = "World"
swapTwoValues(&x, &y) // Работает с String
Стандартные структуры Swift (Array
, Dictionary
, Set
) используют Generics для работы с любыми типами:
let numbers: Array<Int> = [1, 2, 3]
let names: Dictionary<String, Int> = ["Alice": 25, "Bob": 30]
Например, можно создать стек, который работает с любым типом:
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(1)
intStack.push(2)
var stringStack = Stack<String>()
stringStack.push("Swift")
Например, протокол IteratorProtocol
в Swift использует Generics:
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
}
Иногда нужно ограничить типы, с которыми может работать Generic. Например, чтобы тип поддерживал определенный протокол:
func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
for (index, item) in array.enumerated() {
if item == value { // Требует, чтобы T был Equatable
return index
}
}
return nil
}
✅ Повторное использование кода – одна реализация для многих типов.
✅ Безопасность типов – компилятор проверяет типы на этапе компиляции.
✅ Производительность – Generics в Swift реализованы через специализацию, что делает их быстрыми (в отличие, например, от Any
).
Any
– стирает информацию о типе, требует проверки (as?
, as!
) и менее безопасен.
Generics — это ключевая фича Swift, позволяющая писать универсальный, типобезопасный и эффективный код. Они широко применяются в стандартной библиотеке и являются основой для многих абстракций, таких как коллекции (Array
, Dictionary
), алгоритмы (map
, filter
) и пользовательские структуры данных.