Ответ
Generics (обобщения) позволяют писать гибкий, типобезопасный код, который может работать с любыми типами, сохраняя строгую проверку типов на этапе компиляции.
Пример 1: Универсальная функция
// Функция меняет местами два значения любого типа
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 5
var y = 10
swapValues(&x, &y) // Работает с Int
print(x, y) // 10 5
var str1 = "Hello"
var str2 = "World"
swapValues(&str1, &str2) // Работает с String
print(str1, str2) // World Hello
Пример 2: Универсальный тип (Generic Type)
// Универсальная структура Stack
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)
print(intStack.pop()!) // 2
var stringStack = Stack<String>()
stringStack.push("Swift")
Ключевые моменты:
TиElement— это параметры типа (type parameters), заполнители для реальных типов.- Компилятор подставляет конкретные типы, обеспечивая типобезопасность.
- Generics устраняют необходимость дублирования кода для разных типов.
Ответ 18+ 🔞
Ну ты посмотри, какая хуйня придумана, чтобы мозги не ебать! Generics, обобщения, блядь. Это как такой универсальный ключ, который подходит ко всем замкам, но при этом компилятор, этот бдящий пидорас, не даст тебе сунуть его не в ту скважину. Типобезопасность, ёпта! Код гибкий, а ошибки — на этапе компиляции, а не когда уже всё на боевом сервере ебнулось.
Пример 1: Функция, которая меняет всё нахуй
Вот смотри, обычная функция swap, но она может работать с чем угодно. Цифры, строки, да хоть твой старый диван.
// Функция меняет местами два значения любого типа
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 5
var y = 10
swapValues(&x, &y) // Работает с Int
print(x, y) // 10 5
var str1 = "Hello"
var str2 = "World"
swapValues(&str1, &str2) // Работает с String
print(str1, str2) // World Hello
Видишь? Одна функция, а пиздует и с числами, и со словами. T — это типа обещание компилятору: «Не бзди, чувак, я тут сам разберусь, какой тип подставить».
Пример 2: Структура, которая всех складывает в кучу
Допустим, тебе нужен стек. Раньше бы пришлось для Int свой писать, для String свой — пиздец, копипаста овердохуища. А теперь — раз, и универсальный.
// Универсальная структура Stack
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)
print(intStack.pop()!) // 2
var stringStack = Stack<String>()
stringStack.push("Swift")
Создал стек для целых чисел — работает. Создал для строк — тоже пашет. Element — это просто имя для типа-заглушки. Можешь назвать его ChtoUgodno, но так не делают, ибо ты не мудак.
Суть, блядь, в чём:
- Эти буквы
T,Element— параметры типа. Это как слоты, куда потом реальные типы встают. - Компилятор, хитрая жопа, сам всё подставляет и следит, чтобы ты не начал в стек для строк пихать числа. Типобезопасность, ёпта!
- И главное — не нужно плодить один и тот же код для каждого типа. Написал один раз — и ебёт всех. Красота, в рот меня чих-пых!