Spec-Zone .ru
спецификации, руководства, описания, API

Библиотека разработчика XCode

Разработчик

Swift язык программирования

iBook
На этой странице

Обобщения

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

Обобщения являются одной из наиболее мощных функций Swift, и большая часть библиотеки стандарта Swift создается с универсальным кодом. Фактически, Вы использовали обобщения всюду по Руководству по Языку, даже если Вы не понимали его. Например, Swift Array и Dictionary типы являются оба универсальными наборами. Можно создать содержащий массив Int содержащий значения или массив String значения, или действительно массив для любого другого типа, который может быть создан в Swift. Точно так же можно создать словарь для хранения значений любого указанного типа, и нет никаких ограничений на то, каков тот тип может быть.

Проблема, которую решают обобщения

Вот стандарт, вызванная неродовая функция swapTwoInts, который подкачивает два Int значения:

  • func swapTwoInts(inout a: Int, inout b: Int) {
  • let temporaryA = a
  • a = b
  • b = temporaryA
  • }

Эта функция использует изменяемые параметры для свопинга значений a и b, как описано в Изменяемых параметрах.

swapTwoInts функционируйте подкачивает исходное значение b в a, и исходное значение a в b. Можно вызвать эту функцию для свопинга значений в два Int переменные:

  • var someInt = 3
  • var anotherInt = 107
  • swapTwoInts(&someInt, &anotherInt)
  • println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
  • // prints "someInt is now 107, and anotherInt is now 3"

swapTwoInts функция полезна, но она может только использоваться с Int значения. Если Вы хотите подкачать два String значения, или два Double значения, необходимо записать больше функций, такой как swapTwoStrings и swapTwoDoubles функции, показанные ниже:

  • func swapTwoStrings(inout a: String, inout b: String) {
  • let temporaryA = a
  • a = b
  • b = temporaryA
  • }
  • func swapTwoDoubles(inout a: Double, inout b: Double) {
  • let temporaryA = a
  • a = b
  • b = temporaryA
  • }

Вы, возможно, заметили что организации swapTwoInts, swapTwoStrings, и swapTwoDoubles функции идентичны. Единственной разницей является тип значений, которые они принимают (Int, String, и Double).

Это было бы намного более полезным, и значительно более гибким, для записи единственной функции, которая могла подкачать два значения любого типа. Универсальный код позволяет Вам записать такую функцию. (Универсальная версия этих функций определяется ниже.)

Родовые функции

Родовые функции могут работать с любым типом. Вот универсальная версия swapTwoInts функционируйте сверху, вызванные swapTwoValues:

  • func swapTwoValues<T>(inout a: T, inout b: T) {
  • let temporaryA = a
  • a = b
  • b = temporaryA
  • }

Организация swapTwoValues функция идентична организации swapTwoInts функция. Однако первая строка swapTwoValues немного отличается от swapTwoInts. Вот то, как первые строки выдерживают сравнение:

  • func swapTwoInts(inout a: Int, inout b: Int)
  • func swapTwoValues<T>(inout a: T, inout b: T)

Универсальная версия функции использует имя типа заполнителя (вызванный T, в этом случае) вместо фактического имени типа (такой как Int, String, или Double). Имя типа заполнителя ничего не говорит о какой T должен быть, но это действительно говорит это оба a и b должен иметь тот же тип T, безотносительно T представляет. Фактический тип для использования вместо T будет определен каждый раз swapTwoValues функция вызвана.

Другое различие то, что имя родовой функции (swapTwoValues) сопровождается именем типа заполнителя (T) в угловых скобках (<T>). Скобки говорят Swift это T имя типа заполнителя в swapTwoValues функциональное определение. Поскольку T заполнитель, Swift не ищет фактический вызванный тип T.

swapTwoValues функция может теперь быть вызвана таким же образом как swapTwoInts, за исключением того, что это может быть передано два значения любого типа, пока оба из тех значений имеют тот же тип друг как друг. Каждый раз swapTwoValues вызывается, тип для использования для T выведен из типов значений, переданных функции.

В этих двух примерах ниже, T выведен, чтобы быть Int и String соответственно:

  • var someInt = 3
  • var anotherInt = 107
  • swapTwoValues(&someInt, &anotherInt)
  • // someInt is now 107, and anotherInt is now 3
  • var someString = "hello"
  • var anotherString = "world"
  • swapTwoValues(&someString, &anotherString)
  • // someString is now "world", and anotherString is now "hello"

Введите параметры

В swapTwoValues пример выше, тип заполнителя T пример параметра типа. Введите параметры, указывают и называют тип заполнителя и сразу записаны после имени функции, между парой соответствия угловых скобок (такой как <T>).

Как только Вы указываете параметр типа, можно использовать его для определения типа параметров функции (такой как a и b параметры swapTwoValues функция), или как тип возврата функции, или как аннотация типа в организации функции. В каждом случае тип заполнителя, представленный параметром типа, заменяется фактическим типом каждый раз, когда вызвана функция. (В swapTwoValues пример выше, T был заменен Int в первый раз функция была вызвана и была заменена String во второй раз это вызвали.)

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

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

В простых случаях, где родовая функция или универсальный тип относятся к единственному типу заполнителя (такой как swapTwoValues родовая функция выше, или универсальный набор, хранящий единственный тип, такой как Array), традиционно использовать односимвольное имя T для параметра типа. Однако можно использовать любой допустимый идентификатор в качестве названия параметра типа.

При определении более сложных родовых функций или универсальных типов с многократными параметрами полезно обеспечить более дескриптивные названия параметра типа. Например, Swift Dictionary тип имеет два параметра типа — один для его ключей и один для его значений. Если Вы писали Dictionary самостоятельно, Вы могли бы назвать эти два параметра типа Key и Value напомнить Вам об их цели, поскольку Вы используете их в своем универсальном коде.

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

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

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

Иллюстрация ниже шоу нажатие / выталкивает поведение для штабеля:

image: ../Art/stackPushPop_2x.png
  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()
  • }
  • }

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

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

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

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

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

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

  • Создать вызванное свойство items, который инициализируется с пустым массивом значений типа T

  • Указать что push(_:) методу вызвали единственный параметр item, который должен иметь тип T

  • Указать что значение, возвращенное pop() метод будет значением типа T

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

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

  • var stackOfStrings = Stack<String>()
  • stackOfStrings.push("uno")
  • stackOfStrings.push("dos")
  • stackOfStrings.push("tres")
  • stackOfStrings.push("cuatro")
  • // the stack now contains 4 strings

Вот то, как stackOfStrings заботится о продвижении этих четырех значений на штабеле:

image: ../Art/stackPushedFourStrings_2x.png

Сование значения от штабеля возвращает и удаляет главное значение, "cuatro":

  • let fromTheTop = stackOfStrings.pop()
  • // fromTheTop is equal to "cuatro", and the stack now contains 3 strings

Вот то, как штабель заботится о совании его главного значения:

image: ../Art/stackPoppedOneString_2x.png

Расширение универсального типа

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

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

  • extension Stack {
  • var topItem: T? {
  • return items.isEmpty ? nil : items[items.count - 1]
  • }
  • }

topItem свойство возвращает дополнительное значение типа T. Если штабель пуст, topItem возвраты nil; если штабель не пуст, topItem возвращает заключительный элемент в items массив.

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

topItem вычисленное свойство может теперь использоваться с любым Stack экземпляр, чтобы получить доступ и запросить его главный элемент, не удаляя его:

  • if let topItem = stackOfStrings.topItem {
  • println("The top item on the stack is \(topItem).")
  • }
  • // prints "The top item on the stack is tres."

Введите ограничения

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

Например, Swift Dictionary введите помещает ограничение на типы, которые могут использоваться в качестве ключей для словаря. Как описано в Словарях, тип ключей словаря должен быть hashable. Т.е. это должно обеспечить способ сделать себя уникально представимым. Dictionary нуждается в его ключах, чтобы быть hashable так, чтобы это могло проверить, содержит ли это уже значение для определенного ключа. Без этого требования, Dictionary не мог сказать, должно ли это вставить или заменить значение для определенного ключа, и при этом это не было бы в состоянии найти значение для данного ключа, который уже находится в словаре.

Это требование осуществляется ограничением типа на ключевой тип для Dictionary, который указывает, что ключевой тип должен соответствовать Hashable протокол, особый протокол определяется в библиотеке стандарта Swift. Все основные типы Swift (такой как String, Int, Double, и Bool) hashable по умолчанию.

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

Введите ограничительный синтаксис

Вы пишете ограничения типа путем размещения единого класса или ограничения протокола после имени параметра типа, разделенного двоеточием, как часть списка параметров типа. Базовый синтаксис для ограничений типа на родовую функцию показан ниже (несмотря на то, что синтаксис является тем же для универсальных типов):

  • func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
  • // function body goes here
  • }

Гипотетическая функция выше имеет два параметра типа. Первый параметр типа, T, имеет требующее ограничение типа T быть подклассом SomeClass. Второй параметр типа, U, имеет требующее ограничение типа U соответствовать протоколу SomeProtocol.

Введите ограничения в действии

Вот вызванная неродовая функция findStringIndex, которому дают a String значение для нахождения и массив String значения, в которых можно найти его. findStringIndex функционируйте возвращает дополнительное Int значение, которое будет индексом первой соответствующей строки в массиве, если это будет найдено, или nil если не может быть найдена строка:

  • func findStringIndex(array: [String], valueToFind: String) -> Int? {
  • for (index, value) in enumerate(array) {
  • if value == valueToFind {
  • return index
  • }
  • }
  • return nil
  • }

findStringIndex функция может использоваться для нахождения строкового значения в массиве строк:

  • let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
  • if let foundIndex = findStringIndex(strings, "llama") {
  • println("The index of llama is \(foundIndex)")
  • }
  • // prints "The index of llama is 2"

Принцип нахождения индекса значения в массиве не полезен только для строк, как бы то ни было. Можно записать ту же функциональность как вызванная родовая функция findIndex, путем замены любого упоминания о строках со значениями некоторого типа T вместо этого.

Вот то, как Вы могли бы ожидать универсальную версию findStringIndex, вызванный findIndex, быть записанным. Обратите внимание на то, что тип возврата этой функции тих Int?, потому что функция возвращает дополнительный индекс, не дополнительное значение от массива. Будьте предупреждены, хотя — эта функция не компилирует по причинам, объясненным после примера:

  • func findIndex<T>(array: [T], valueToFind: T) -> Int? {
  • for (index, value) in enumerate(array) {
  • if value == valueToFind {
  • return index
  • }
  • }
  • return nil
  • }

Эта функция не компилирует, как записано выше. Проблема связана с проверкой равенства, “if value == valueToFind”. Не каждый тип в Swift может быть по сравнению с равным оператору (==). Если Вы создаете свой собственный класс или структуру для представления сложной модели данных, например, то значение “равного” для того класса или структуры не является чем-то, что Swift может предположить для Вас. Из-за этого не возможно гарантировать, что этот код будет работать на каждый возможный тип T, когда Вы пытаетесь скомпилировать код, и сообщают о надлежащей ошибке.

Не все потеряно, как бы то ни было. Библиотека стандарта Swift определяет вызванный протокол Equatable, который требует, чтобы любой тип приспосабливания реализовал равное оператору (==) и не равняются оператору (!=) сравнить любые два значения того типа. Все стандартные типы Swift автоматически поддерживают Equatable протокол.

Любой тип, который является Equatable может использоваться безопасно с findIndex функция, потому что это, как гарантируют, будет поддерживать равное оператору. Для выражения этого факта Вы пишете ограничение типа Equatable как часть определения параметра типа, когда Вы определяете функцию:

  • func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
  • for (index, value) in enumerate(array) {
  • if value == valueToFind {
  • return index
  • }
  • }
  • return nil
  • }

Единственный параметр типа для findIndex записан как T: Equatable, что означает “любой тип T это соответствует Equatable протокол”.

findIndex функционируйте теперь компилирует успешно и может использоваться с любым типом, который является Equatable, такой как Double или String:

  • let doubleIndex = findIndex([3.14159, 0.1, 0.25], 9.3)
  • // doubleIndex is an optional Int with no value, because 9.3 is not in the array
  • let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea")
  • // stringIndex is an optional Int containing a value of 2

Связанные типы

При определении протокола иногда полезно объявить один или несколько связанные типы как часть определения протокола. Связанный тип дает имя заполнителя (или псевдоним) к типу, использующемуся в качестве части протокола. Фактический тип для использования для того связанного типа не указан, пока протокол не принят. Связанные типы указаны с typealias ключевое слово.

Связанные типы в действии

Вот пример вызванного протокола Container, который объявляет связанный вызванный тип ItemType:

  • protocol Container {
  • typealias ItemType
  • mutating func append(item: ItemType)
  • var count: Int { get }
  • subscript(i: Int) -> ItemType { get }
  • }

Container протокол определяет три требуемых возможности, которые должен обеспечить любой контейнер:

  • Должно быть возможно добавить новый элемент к контейнеру с append(_:) метод.

  • Должно быть возможно получить доступ к количеству элементов в контейнере через a count свойство, возвращающееся Int значение.

  • Должно быть возможно получить каждый элемент в контейнере с нижним индексом, берущим Int индексное значение.

Этот протокол не указывает, как элементы в контейнере должны быть сохранены или что вводит, им позволяют быть. Протокол только указывает три бита функциональности, которую любой тип должен обеспечить для рассмотрения a Container. Соответствующий тип может обеспечить дополнительную функциональность, пока это удовлетворяет эти три требования.

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

Определить эти требования, Container для протокола нужен способ относиться к типу элементов, которые контейнер будет содержать, не зная то, что тот тип для определенного контейнера. Container протокол должен указать, что любое значение передало append(_:) метод должен иметь тот же тип как тип элемента контейнера, и что значение, возвращенное нижним индексом контейнера, будет иметь тот же тип как тип элемента контейнера.

Достигнуть этого, Container протокол объявляет связанный вызванный тип ItemType, записанный как typealias ItemType. Протокол не определяет что ItemType псевдоним для — что информация оставлена для любого типа приспосабливания для обеспечения. Тем не менее, ItemType псевдоним обеспечивает способ относиться к типу элементов в a Container, и определить тип для использования с append(_:) метод и нижний индекс, чтобы гарантировать, что ожидаемое поведение любого Container осуществляется.

Вот версия необобщения IntStack введите от ранее, адаптированный для приспосабливания Container протокол:

  • struct IntStack: Container {
  • // original IntStack implementation
  • var items = [Int]()
  • mutating func push(item: Int) {
  • items.append(item)
  • }
  • mutating func pop() -> Int {
  • return items.removeLast()
  • }
  • // conformance to the Container protocol
  • typealias ItemType = Int
  • mutating func append(item: Int) {
  • self.push(item)
  • }
  • var count: Int {
  • return items.count
  • }
  • subscript(i: Int) -> Int {
  • return items[i]
  • }
  • }

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

Кроме того, IntStack указывает это для этой реализации Container, надлежащее ItemType использовать - тип Int. Определение typealias ItemType = Int поворачивает абстрактный тип ItemType в конкретный тип Int для этой реализации Container протокол.

Благодаря выводу типа Swift Вы не должны фактически объявлять бетон ItemType из Int как часть определения IntStack. Поскольку IntStack соответствует всем требованиям Container протокол, Swift может вывести надлежащее ItemType использовать, просто путем рассмотрения типа append(_:) метод item параметр и тип возврата нижнего индекса. Действительно, если Вы удаляете typealias ItemType = Int строка от кода выше, все все еще работает, потому что ясно, для чего должен использоваться тип ItemType.

Можно также сделать обобщение Stack тип соответствует Container протокол:

  • struct Stack<T>: Container {
  • // original Stack<T> implementation
  • var items = [T]()
  • mutating func push(item: T) {
  • items.append(item)
  • }
  • mutating func pop() -> T {
  • return items.removeLast()
  • }
  • // conformance to the Container protocol
  • mutating func append(item: T) {
  • self.push(item)
  • }
  • var count: Int {
  • return items.count
  • }
  • subscript(i: Int) -> T {
  • return items[i]
  • }
  • }

На сей раз, параметр типа заполнителя T используется в качестве типа append(_:) метод item параметр и тип возврата нижнего индекса. Swift может поэтому вывести это T надлежащий тип для использования в качестве ItemType для этого определенного контейнера.

Расширение существующего типа для указания связанного типа

Можно расширить существующий тип для добавления соответствия к протоколу, как описано в Добавляющем Соответствии Протокола с Расширением. Это включает протокол со связанным типом.

Swift Array тип уже обеспечивает append(_:) метод, a count свойство и нижний индекс с Int индекс для получения его элементов. Эти три возможности соответствуют требования Container протокол. Это означает, что можно расшириться Array соответствовать Container протокол просто путем объявления этого Array принимает протокол. Вы делаете это с пустым расширением, как описано в Объявлении Принятия Протокола с Расширением:

  • extension Array: Container {}

Существующий массив append(_:) метод и нижний индекс позволяют Swift вывести надлежащий тип для использования для ItemType, так же, как для обобщения Stack введите выше. После определения этого расширения можно использовать любого Array как a Container.

Операторы Where

Введите ограничения, как описано в Ограничениях Типа, позвольте Вам определить требования к параметрам типа, связанным с родовой функцией или типом.

Может также быть полезно определить требования для связанных типов. Вы делаете это путем определения где пункты как часть списка параметров типа. Где пункт позволяет Вам потребовать, чтобы связанный тип соответствовал определенному протоколу, и/или что параметры определенного типа и связали типы быть тем же. Вы пишете где пункт путем размещения where ключевое слово сразу после списка параметров типа, сопровождаемых одним или более ограничениями для связанных типов и/или одним или более отношениями равенства между типами и связанными типами.

Пример ниже определяет вызванную родовую функцию allItemsMatch, который проверяет, чтобы видеть если два Container экземпляры содержат те же элементы в том же порядке. Функция возвращает булево значение true если все элементы соответствуют и значение false если они не делают.

Эти два контейнера, которые будут проверены, не должны быть тем же типом контейнера (несмотря на то, что они могут быть), но они действительно должны содержать тот же тип элементов. Это требование выражено через комбинацию ограничений типа и где пункты:

  • func allItemsMatch<
  • C1: Container, C2: Container
  • where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
  • (someContainer: C1, anotherContainer: C2) -> Bool {
  • // check that both containers contain the same number of items
  • if someContainer.count != anotherContainer.count {
  • return false
  • }
  • // check each pair of items to see if they are equivalent
  • for i in 0..<someContainer.count {
  • if someContainer[i] != anotherContainer[i] {
  • return false
  • }
  • }
  • // all items match, so return true
  • return true
  • }

Эта функция берет два вызванные параметра someContainer и anotherContainer. someContainer параметр имеет тип C1, и anotherContainer параметр имеет тип C2. Оба C1 и C2 параметры типа заполнителя для двух контейнерных типов, которые будут определены, когда вызвана функция.

Список параметров типа функции налагает следующие требования на два параметра типа:

  • C1 должен соответствовать Container протокол (записанный как C1: Container).

  • C2 должен также соответствовать Container протокол (записанный как C2: Container).

  • ItemType для C1 должен совпасть с ItemType для C2 (записанный как C1.ItemType == C2.ItemType).

  • ItemType для C1 должен соответствовать Equatable протокол (записанный как C1.ItemType: Equatable).

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

Эти требования среднее значение:

  • someContainer контейнер типа C1.

  • anotherContainer контейнер типа C2.

  • someContainer и anotherContainer содержите тот же тип элементов.

  • Элементы в someContainer может быть сверен не, равняются оператору (!=) видеть, отличаются ли они друг от друга.

Третьи и четвертые требования объединяются, чтобы означать что элементы в anotherContainer может также быть сверен != оператор, потому что они - точно тот же тип как элементы в someContainer.

Эти требования включают allItemsMatch функция для сравнения этих двух контейнеров, даже если они имеют различный контейнерный тип.

allItemsMatch функция запускается путем проверки, что оба контейнера содержат то же число элементов. Если они содержат различное число элементов, нет никакого способа, которым они могут соответствовать, и функциональные возвраты false.

После осуществления этой проверки функция выполняет итерации по всем элементам в someContainer с a for-in цикл и полуоткрытый оператор диапазона (..<). Для каждого элемента функция проверяет ли элемент от someContainer не равно соответствующему элементу в anotherContainer. Если эти два элемента не равны, то эти два контейнера не соответствуют, и функциональные возвраты false.

Если цикл заканчивается, не находя несоответствие, эти два соответствия контейнеров и функциональные возвраты true.

Вот то, как allItemsMatch функциональные взгляды в действии:

  • var stackOfStrings = Stack<String>()
  • stackOfStrings.push("uno")
  • stackOfStrings.push("dos")
  • stackOfStrings.push("tres")
  • var arrayOfStrings = ["uno", "dos", "tres"]
  • if allItemsMatch(stackOfStrings, arrayOfStrings) {
  • println("All items match.")
  • } else {
  • println("Not all items match.")
  • }
  • // prints "All items match."

Пример выше создает a Stack экземпляр для хранения String значения и нажатия три строки на штабель. Пример также создает Array экземпляр, инициализированный с литералом массивов, содержащим те же три строки как штабель. Даже при том, что штабель и массив имеют другой тип, они оба соответствуют Container протокол, и оба содержат тот же тип значений. Можно поэтому вызвать allItemsMatch функция с этими двумя контейнерами как ее параметры. В примере выше, allItemsMatch функционируйте правильно сообщает, что соответствуют все элементы в этих двух контейнерах.