0Pricing
Swift Academy · Урок

Ограничение ассоциированных типов

Ограничивайте ассоциированные типы в обобщённых контекстах.

«Ограничение ассоциированных типов» — бесплатный урок Swift Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.

Итоги по связанным типам

Протокол может объявить связанный тип с помощью associatedtype — это заполнитель, которому соответствующий тип назначает конкретное значение. Классический пример — Element в протоколе контейнера.

protocol Container {
    associatedtype Item
    var count: Int { get }
    func item(at i: Int) -> Item
}

Соответствие с конкретным типом

Соответствующий тип фиксирует связанный тип, который часто выводится из способа его использования.

protocol Container {
    associatedtype Item
    func item(at i: Int) -> Item
}
struct IntBox: Container {
    let values: [Int]
    func item(at i: Int) -> Int { values[i] }
}
print(IntBox(values: [10, 20]).item(at: 1))

Ограничение связанного типа

Добавьте ограничение прямо в объявление: associatedtype Item: Comparable требует, чтобы тип элемента каждого соответствующего типа поддерживал сравнение.

protocol Sorted {
    associatedtype Item: Comparable
    var items: [Item] { get }
}
struct Nums: Sorted { let items: [Int] }
print(Nums(items: [3, 1, 2]).items.sorted())

Использование ограничения

Поскольку связанный тип ограничен, расширения протокола могут полагаться на эту возможность.

protocol Sorted {
    associatedtype Item: Comparable
    var items: [Item] { get }
}
extension Sorted {
    var smallest: Item? { items.min() }
}
struct Nums: Sorted { let items: [Int] }
print(Nums(items: [5, 2, 8]).smallest!)

where для associatedtype

Swift также позволяет использовать условие where для связанного типа, чтобы связать его с другим связанным или вложенным типом.

protocol Sequence2 {
    associatedtype Element
    associatedtype Iterator: IteratorProtocol where Iterator.Element == Element
}

Ограничение другим протоколом

Для связанного типа можно потребовать соответствия определённому Вами протоколу, постепенно добавляя поведение.

protocol HasName { var name: String { get } }
protocol Registry {
    associatedtype Entry: HasName
    var entries: [Entry] { get }
}
struct User: HasName { let name: String }
struct Users: Registry { let entries: [User] }
print(Users(entries: [User(name: "Ada")]).entries[0].name)

Несколько связанных типов

Протокол может объявлять несколько связанных типов, каждый со своими независимыми ограничениями.

protocol Mapping {
    associatedtype Key: Hashable
    associatedtype Value
    func value(for k: Key) -> Value?
}
struct Phonebook: Mapping {
    let data: [String: Int]
    func value(for k: String) -> Int? { data[k] }
}
print(Phonebook(data: ["x": 1]).value(for: "x")!)

Связанный тип по умолчанию

Связанному типу можно задать значение по умолчанию с помощью =. Оно используется, если соответствующий тип не указывает другое значение.

protocol Producer {
    associatedtype Output = String
    func make() -> Output
}
struct Hello: Producer {
    func make() -> String { "hi" }
}
print(Hello().make())

Ограничения открывают доступ к обобщённым алгоритмам

Имея ограниченный связанный тип, расширение протокола может реализовать полноценные алгоритмы, общие для всех соответствующих типов.

protocol Scored {
    associatedtype Score: Comparable
    var scores: [Score] { get }
}
extension Scored {
    var best: Score? { scores.max() }
}
struct Game: Scored { let scores: [Int] }
print(Game(scores: [10, 40, 25]).best!)

Ограничения равенства типов в расширениях

За пределами протокола можно дополнительно ограничить связанный тип при расширении протокола.

protocol Box2 {
    associatedtype Content
    var content: Content { get }
}
extension Box2 where Content == Int {
    var doubled: Int { content * 2 }
}
struct IB: Box2 { let content: Int }
print(IB(content: 7).doubled)

Зачем устанавливать ограничения

Ограничение связанных типов позволяет протоколам оставаться обобщёнными и при этом мощными: это обещание, на которое могут рассчитывать расширение и вызывающий код.

protocol Listy {
    associatedtype E: Equatable
    var elements: [E] { get }
}
extension Listy {
    func has(_ x: E) -> Bool { elements.contains(x) }
}
struct L: Listy { let elements: [String] }
print(L(elements: ["a", "b"]).has("b"))

Проверка понимания

Проверьте, насколько хорошо Вы поняли ограничения связанных типов.

Итоги

Вы можете напрямую ограничивать связанные типы (associatedtype Item: Comparable), связывать их условиями where, требовать соответствия протоколу, задавать значения по умолчанию с помощью =, объявлять несколько связанных типов и уточнять их в расширениях. Ограничения позволяют расширениям протоколов реализовывать общие алгоритмы с проверкой типов.

Часто задаваемые вопросы

Урок «Ограничение ассоциированных типов» бесплатный?

Да — полный текст урока «Ограничение ассоциированных типов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.

Чему я научусь в уроке «Ограничение ассоциированных типов»?

Ограничивайте ассоциированные типы в обобщённых контекстах. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Swift Academy?

Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Ограничение ассоциированных типов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Swift Academy?

Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Ограничения параметров типов
  2. Предложения where в функциях
  3. Ограничение ассоциированных типов
  4. Обобщённые индексы и расширения
← Назад к Swift Academy