Видеокурсы по изучению языка программирования Swift. Подробнее

Именование параметров типа

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

В большинстве случаев параметры типа имеют описательные имена, такие как Key и Value в Dictionary<Key, Value> и Element в Array<Element>, которые помогут читающему код определить взаимосвязь между параметром типа и универсальным типом или функцией, в которых он используется. Тем не менее, когда между ними нет значимых отношений, то по традиции именами становятся отдельные буквы, такие как T, U, V, как например T в функции swapTwoValues(_:_:).

Заметка

Всегда давайте параметрам типа имена "горбатого" верхнего регистра (например, T и MyTypeParameter), чтобы указать, что они являются заполнителем для типа, а не значением.

Универсальные типы

В дополнение к универсальным функциям, Swift позволяет вам определять ваши универсальные типы. Это к примеру универсальные классы, структуры и перечисления, которые могут работать с любыми типами, на подобии тому, как работают Array или Dictionary.

Эта секция покажет вам как создать вашу универсальную коллекцию типа Stack. Stack - упорядоченная коллекция значений, аналогичная массиву, но с более строгим набором операций, чем имеет типа Array языка Swift. Массив позволяет вам вставлять и удалять элементы с любой позиции массива. Однако, Stack позволяет добавлять новые элементы только в конец коллекции (известно как заталкивание (или pushing на англ) нового значения в стек). Аналогично стек позволяет удалять элементы только с конца коллекции (известно как выстреливать значение из стека (или popping по англ).

Заметка

Концепция стека используется классом UINavigationController для моделирования контроллеров видов в его иерархии навигации. Вы вызываете метод pushViewController(_:animated:) класса UINavigationController для добавления контроллера вида на стек навигации, а метод popViewControllerAnimated(_:) для удаления контроллера вида из стека навигации. Стек - полезная модель коллекции, когда вам нужен строгий принцип “последний на вход - первый на выход”.

Ниже приведена иллюстрация поведения добавления и удаления элемента из стека:

  1. На данный момент у нас три значения в стеке.
  2. Четвертое значение “затолкнули” на самый верх стека.
  3. На этот момент в стеке находится три значения, самое свежее значение находится наверху.
  4. Последнее значение удалено или “выстреляно” из стека.
  5. После удаления значения, стек снова имеет три значения.

Вот как написать не универсальную версию стека, в этом случае мы используем стек для хранения Int значений:

struct IntStack {
    var items = [Int]()
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
}

Эта структура использует свойство items типа Array для хранения значений в стеке. Stack предоставляет нам два метода, push и pop для добавления последнего элемента в стек и для удаления последнего элемента из стека. Эти методы отмечены как mutating, потому как они вынуждены менять массив items.

Тип IntStack, показанный выше, может быть использован только со значениями Int. Но он будет куда полезнее, если мы определим его как универсальный класс Stack, который может управлять стеком любого типа.

Вот универсальная версия структуры:

struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

Обратите внимание как универсальная версия Stack похожа на не универсальную, вообще отличаясь только тем, что мы используем заполнитель типа, вместо указания конкретного типа Int. Этот параметр типа написан внутри угловых скобок ( <Element>), сразу после имени структуры.

Element определяет заполнитель имени типа для “какого-то типа Element”, который будет предоставлен позже. Этот будущий тип может быть сослан на Element в любом месте определения структуры. В этом случае наш некоторый тип Element используется в трех местах:

  • Для создания свойства items, которое инициализируется пустым массивом типа Element.
  • Для указания того, что метод push(_:) имеет единственный параметр item, который должен быть типа Element.
  • Для указания типа возвращаемого значения методом pop(), которое должно быть типом Element.

Из-за того, что это является универсальным типом, то Stack может быть использован для создания стека любых корректных типов в Swift, аналогичным образом как это осуществляют типы Array или Dictionary.

Вы создаете новый экземпляр Stack, вписав тип хранимых значений стека в угловые скобки. Например, создадим новый стек строк, вы напишите Stack<String>():

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// stack содержит 4 строки

Теперь stackOfStrings выглядит вот так после добавления последних четырех значений:

Удаляя последнее значение, он возвращает его и удаляет его из стека “cuatro”:

let fromTheTop = stackOfStrings.pop()
// fromTheTop равен "cuatro", а stack содержит 3 строки

После удаления верхней величины, стек выглядит так:

 

Swift: 
4.0