← Назад к вопросам

Где используются Generics?

1.3 Junior🔥 201 комментариев
#Язык Swift

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Generics в Swift: области применения

Generics — один из мощнейших инструментов Swift, позволяющий писать гибкий, переиспользуемый и type-safe код. Я использую их практически в каждом проекте. Позволь разобраться, где и почему они необходимы.

1. Контейнеры данных и коллекции

Основное применение generics — создание контейнеров, работающих с любыми типами:

// Свой Stack (стек)
struct Stack<Element> {
    private var elements: [Element] = []
    
    mutating func push(_ element: Element) {
        elements.append(element)
    }
    
    mutating func pop() -> Element? {
        elements.popLast()
    }
}

// Использование с любым типом
var intStack = Stack<Int>()
intStack.push(42)

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

Без generics пришлось бы писать отдельные классы для каждого типа — Stack<Int>, Stack<String>, Stack<Custom>, что нарушает DRY принцип.

2. Сетевые запросы и API клиенты

Это классическое применение generics в реальных приложениях:

// Универсальный API клиент
class APIClient<Response: Decodable> {
    func fetch<T: Decodable>(url: URL) async throws -> T {
        let (data, response) = try await URLSession.shared.data(from: url)
        
        guard (response as? HTTPURLResponse)?.statusCode == 200 else {
            throw APIError.invalidResponse
        }
        
        return try JSONDecoder().decode(T.self, from: data)
    }
}

struct User: Decodable {
    let id: Int
    let name: String
}

// Использование
let client = APIClient<User>()
let user = try await client.fetch(url: userURL)

Так один код работает с User, Product, Post или любым другим Decodable типом.

3. Обобщённые алгоритмы и утилиты

Mногие вспомогательные функции требуют работы с разными типами:

// Поиск элемента в массиве
func findFirst<Element: Equatable>(in array: [Element], where predicate: (Element) -> Bool) -> Element? {
    for element in array {
        if predicate(element) {
            return element
        }
    }
    return nil
}

// Использование
let numbers = [1, 2, 3, 4, 5]
let firstEven = findFirst(in: numbers) { $0 % 2 == 0 }  // 2

let names = ["Alice", "Bob", "Charlie"]
let firstLong = findFirst(in: names) { $0.count > 4 }  // "Alice"

4. Constraints и Protocol-oriented Programming

Generics с constraints позволяют ограничить типы, но оставить гибкость:

// Только типы, конформирующие Comparable
func findMin<T: Comparable>(in array: [T]) -> T? {
    return array.min()
}

// Constraints на несколько протоколов
func encode<T: Codable>(object: T) throws -> Data {
    return try JSONEncoder().encode(object)
}

// Constraints на конкретный класс
class Repository<Model: NSObject> {
    func save(_ model: Model) {
        // Работаем с Model как с NSObject
    }
}

5. ViewModels и Reactive Programming

В MVVM паттерне generics позволяют создавать универсальные вью-модели:

class ViewModel<State> {
    @Published var state: State
    @Published var error: Error?
    
    init(initialState: State) {
        self.state = initialState
    }
}

// Для разных экранов
let userViewModel = ViewModel<UserState>(initialState: .loading)
let feedViewModel = ViewModel<FeedState>(initialState: .empty)

6. Builder Pattern и DSL

Generics используются в современных DSL и builder паттернах:

struct QueryBuilder<T> {
    private var filters: [(T) -> Bool] = []
    
    func filter(_ predicate: @escaping (T) -> Bool) -> QueryBuilder<T> {
        var copy = self
        copy.filters.append(predicate)
        return copy
    }
    
    func execute(on array: [T]) -> [T] {
        array.filter { item in
            filters.allSatisfy { $0(item) }
        }
    }
}

Почему Generics важны

  • Type Safety — компилятор проверяет типы на этапе компиляции
  • Code Reuse — один код работает с множеством типов
  • Performance — нет необходимости в boxing/unboxing (в отличие от AnyObject)
  • Readability — код более понятен и самодокументируется

Generics — это не просто фишка языка, это фундамент современной Swift разработки.

Где используются Generics? | PrepBro