0Pricing
Swift Academy · Урок

Обобщённые индексы и расширения

Применяйте ограничения к индексам и расширениям.

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

Обобщённые сабскрипты

Сабскрипты могут быть обобщёнными и иметь собственные параметры типов, независимые от окружающего типа. Благодаря этому один сабскрипт может работать со множеством типов входных данных.

struct Lookup {
    let data = [1, 2, 3, 4, 5]
    subscript<S: Sequence>(indices idx: S) -> [Int] where S.Element == Int {
        idx.map { data[$0] }
    }
}
print(Lookup()[indices: [0, 2, 4]])

Зачем нужны обобщённые сабскрипты

Можно передать один и тот же сабскрипт Array, Set или Range индексов, потому что он принимает любую Sequence из Int.

struct Lookup {
    let data = [10, 20, 30, 40]
    subscript<S: Sequence>(_ idx: S) -> [Int] where S.Element == Int {
        idx.map { data[$0] }
    }
}
let l = Lookup()
print(l[0...1])
print(l[[3, 0]])

Расширения с ограничениями

Конструкция extension ... where добавляет члены, существующие только при выполнении ограничения. Они появляются в типе лишь для подходящих обобщённых аргументов.

extension Array where Element: Numeric {
    func sumAll() -> Element { reduce(0, +) }
}
print([1, 2, 3].sumAll())
print([1.5, 2.5].sumAll())

Расширение для конкретного типа элементов

Используйте where Element == String, чтобы добавлять помощники для строк только в массивы строк.

extension Array where Element == String {
    func shout() -> [String] { map { $0.uppercased() + "!" } }
}
print(["hi", "bye"].shout())

Расширение с ограничением протоколом

Добавляйте поведение, когда элементы соответствуют пользовательскому протоколу.

protocol Priced { var price: Double { get } }
struct Item: Priced { let price: Double }
extension Collection where Element: Priced {
    var total: Double { reduce(0) { $0 + $1.price } }
}
print([Item(price: 2), Item(price: 3)].total)

Обобщённый сабскрипт, возвращающий необязательное значение

Сабскрипт может быть обобщённым и возвращать необязательное значение, например для безопасного обращения к элементу коллекции по индексу.

extension Array {
    subscript(safe i: Int) -> Element? {
        indices.contains(i) ? self[i] : nil
    }
}
print([1, 2, 3][safe: 1] ?? -1)
print([1, 2, 3][safe: 9] ?? -1)

Обобщённый сабскрипт для словаря

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

extension Dictionary {
    subscript<S: Sequence>(keys ks: S) -> [Value] where S.Element == Key {
        ks.compactMap { self[$0] }
    }
}
let d = ["a": 1, "b": 2, "c": 3]
print(d[keys: ["a", "c"]].sorted())

Сочетание с where для Self

Расширения обобщённых типов могут ограничивать обёрнутый тип, предоставляя специально подобранные программные интерфейсы.

struct Stack<T> { var items: [T] = [] }
extension Stack where T: Comparable {
    var peakMax: T? { items.max() }
}
var s = Stack<Int>(); s.items = [3, 9, 1]
print(s.peakMax!)

Обобщённый сабскрипт с несколькими параметрами

Сабскрипт может одновременно принимать несколько аргументов и собственные параметры типов.

struct Grid {
    let rows = [[1, 2], [3, 4]]
    subscript(_ r: Int, _ c: Int) -> Int { rows[r][c] }
}
print(Grid()[1, 0])

Только чтение и чтение с записью

Как и свойства, сабскрипты могут иметь только get или одновременно get и set для изменения значения.

struct Pad {
    var values = [0, 0, 0]
    subscript(i: Int) -> Int {
        get { values[i] }
        set { values[i] = newValue }
    }
}
var p = Pad(); p[1] = 7
print(p.values)

Объединение возможностей

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

extension Array where Element: Comparable {
    subscript(topAfterSort i: Int) -> Element { sorted()[i] }
}
print([5, 1, 9, 3][topAfterSort: 0])

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

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

Итоги

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

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

Урок «Обобщённые индексы и расширения» бесплатный?

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

Чему я научусь в уроке «Обобщённые индексы и расширения»?

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

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

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

Сколько времени занимает урок «Обобщённые индексы и расширения»?

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

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

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

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

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