Swift - Краткое руководство

Swift 4 - это новый язык программирования, разработанный Apple Inc для разработки под iOS и OS X. Swift 4 использует лучшее из C и Objective-C без ограничений совместимости с C.

  • Swift 4 использует безопасные шаблоны программирования.

  • Swift 4 предоставляет современные возможности программирования.

  • Swift 4 предоставляет синтаксис, подобный Objective-C.

  • Swift 4 - отличный способ писать приложения для iOS и OS X.

  • Swift 4 обеспечивает беспрепятственный доступ к существующим фреймворкам какао.

  • Swift 4 объединяет процедурную и объектно-ориентированную части языка.

  • Swift 4 не требует отдельного импорта библиотеки для поддержки таких функций, как ввод / вывод или обработка строк.

Swift 4 использует ту же среду выполнения, что и существующая система Obj-C в Mac OS и iOS, что позволяет программам Swift 4 работать на многих существующих платформах iOS 6 и OS X 10.8.

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

Первый публичный релиз Swift был выпущен в 2010 году. Chris Lattnerпочти 14 лет, чтобы придумать первую официальную версию, а позже ее поддержали многие другие участники. Swift 4 был включен в бета-версию Xcode 6.

Дизайнеры Swift позаимствовали идеи из других популярных языков, таких как Objective-C, Rust, Haskell, Ruby, Python, C # и CLU.

Настройка локальной среды

Swift 4 предоставляет платформу Playground для обучения, и мы собираемся ее настроить. Вам нужно программное обеспечение xCode, чтобы начать кодирование Swift 4 в Playground. Когда вы освоитесь с концепциями Swift 4, вы можете использовать xCode IDE для разработки приложений iOS / OS x.

Для начала мы считаем, что у вас уже есть учетная запись на веб-сайте Apple Developer. После входа в систему перейдите по следующей ссылке - Загрузить для разработчиков Apple

Это перечислит количество доступного программного обеспечения следующим образом:

Теперь выберите xCode и загрузите его, щелкнув указанную ссылку рядом с образом диска. После загрузки файла dmg вы можете установить его, просто дважды щелкнув по нему и следуя данным инструкциям. Наконец, следуйте приведенным инструкциям и поместите значок xCode в папку приложения.

Теперь на вашем компьютере установлен xCode. Затем откройте Xcode из папки «Приложение» и продолжите после принятия условий. Если все в порядке, вы получите следующий экран -

Выбрать Get started with a playgroundвариант и введите название игровой площадки и выберите iOS в качестве платформы. Наконец, вы получите следующее окно игровой площадки -

Ниже приведен код, взятый из окна игровой площадки Swift 4 по умолчанию.

import UIKit
var str = "Hello, playground"

Если вы создадите ту же программу для программы OS X, она будет включать импорт Cocoa, и программа будет выглядеть следующим образом:

import Cocoa
var str = "Hello, playground"

Когда вышеуказанная программа загружается, она должна отображать следующий результат в области результатов Playground (правая сторона).

Hello, playground

Поздравляем, ваша среда программирования Swift 4 готова, и вы можете приступить к изучению своего учебного пособия «Tutorials Point».

Мы уже видели фрагмент программы Swift 4 при настройке среды. Начнем еще раз со следующегоHello, World! программа, созданная для игровой площадки OS X, которая включает import Cocoa как показано ниже -

/* My first program in Swift 4 */
var myString = "Hello, World!"

print(myString)

Если вы создадите такую ​​же программу для игровой площадки iOS, то она будет включать import UIKit и программа будет выглядеть следующим образом -

import UIKit
var myString = "Hello, World!"
print(myString)

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

Hello, World!

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

Импорт в Swift 4

Вы можете использовать importдля импорта любой структуры Objective-C (или библиотеки C) непосредственно в вашу программу Swift 4. Например, приведенный вышеimport cocoa оператор делает все библиотеки Cocoa, API и среды выполнения, которые образуют уровень разработки для всей OS X, доступными в Swift 4.

Какао реализовано в Objective-C, который является надмножеством C, поэтому легко смешивать C и даже C ++ в ваших приложениях Swift 4.

Токены в Swift 4

Программа Swift 4 состоит из различных токенов, и токен представляет собой ключевое слово, идентификатор, константу, строковый литерал или символ. Например, следующий оператор Swift 4 состоит из трех токенов -

print("test!")
The individual tokens are:
print("test!")

Комментарии

Комментарии похожи на вспомогательные тексты в вашей программе на Swift 4. Компилятор игнорирует их. Многострочные комментарии начинаются с / * и заканчиваются символами * /, как показано ниже -

/* My first program in Swift 4 */

Многострочные комментарии могут быть вложены в Swift 4. Ниже приведен действительный комментарий в Swift 4:

/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */

Однострочные комментарии записываются с помощью // в начале комментария.

// My first program in Swift 4

Точка с запятой

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

Однако, если вы используете несколько операторов в одной строке, то необходимо использовать точку с запятой в качестве разделителя, иначе компилятор выдаст синтаксическую ошибку. Вы можете написать выше Hello, World! программа следующим образом -

/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)

Идентификаторы

Идентификатор Swift 4 - это имя, используемое для идентификации переменной, функции или любого другого определяемого пользователем элемента. Идентификатор начинается с алфавита от A до Z, от a до z или символа подчеркивания _, за которым следует ноль или более букв, подчеркиваний и цифр (от 0 до 9).

Swift 4 не позволяет использовать в идентификаторах специальные символы, такие как @, $ и%. Swift 4 - этоcase sensitiveязык программирования. Таким образом, рабочая сила и рабочая сила - это два разных идентификатора в Swift 4. Вот несколько примеров приемлемых идентификаторов:

Azad        zara   abc   move_name   a_123
myname50    _temp  j     a23b9       retVal

Чтобы использовать зарезервированное слово в качестве идентификатора, вам нужно поставить обратную кавычку (`) до и после него. Например,class не является допустимым идентификатором, но `class`действительно.

Ключевые слова

Следующие ключевые слова зарезервированы в Swift 4. Эти зарезервированные слова не могут использоваться как константы, переменные или любые другие имена идентификаторов, если они не экранированы обратными кавычками -

Ключевые слова, используемые в объявлениях

Класс deinit Enum расширение
Func импорт В этом внутренний
Позволять оператор частный протокол
общественный статический структура нижний индекс
typealias вар

Ключевые слова, используемые в заявлениях

сломать дело Продолжить по умолчанию
делать еще провалиться за
если в возвращение переключатель
где в то время как

Ключевые слова, используемые в выражениях и типах

в виде dynamicType ложный является
ноль я Я супер
правда _COLUMN_ _ФАЙЛ_ _FUNCTION_
_ЛИНИЯ_

Ключевые слова, используемые в определенных контекстах

ассоциативность удобство динамичный didSet
окончательный получить инфикс inout
ленивый слева мутирующий никто
не мутирующий необязательный отменять постфикс
приоритет приставка Протокол обязательный
правильно набор Тип бесхозный
слабый willSet

Пробелы

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

Пробел - это термин, используемый в Swift 4 для описания пробелов, табуляции, символов новой строки и комментариев. Пробелы отделяют одну часть оператора от другой и позволяют компилятору определить, где заканчивается один элемент в операторе, например int, и начинается следующий элемент. Следовательно, в следующем заявлении -

var age

Должен быть хотя бы один символ пробела (обычно пробел) между var и ageчтобы компилятор мог их различать. С другой стороны, в следующем заявлении -

int fruit = apples + oranges   //get the total fruits

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

Пространство с обеих сторон оператора должно быть одинаковым, например.

int fruit = apples +oranges    //is a wrong statement
int fruit = apples + oranges   //is a Correct statement

Литералы

Литерал - это представление исходного кода значения целого числа, числа с плавающей запятой или строкового типа. Ниже приведены примеры литералов -

92               // Integer literal
4.24159          // Floating-point literal
"Hello, World!"  // String literal

Печать в Swift

Чтобы быстро распечатать что-либо, у нас есть ключевое слово print.

Печать имеет три различных свойства.

Items - Элементы для печати

Separator - разделитель между элементами

Terminator - значение, которым должна заканчиваться строка, давайте посмотрим на пример и синтаксис.

print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.

print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.

print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"

В приведенном выше коде первый оператор печати по умолчанию добавляет \ n, символ новой строки Feed в качестве терминатора, где, как и во втором операторе печати, мы указали «End» в качестве терминатора, поэтому он будет печатать «End» вместо \ n.

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

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

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

Встроенные типы данных

Swift 4 предлагает программисту богатый набор как встроенных, так и определяемых пользователем типов данных. Следующие типы основных типов данных наиболее часто используются при объявлении переменных:

  • Int or UInt- Используется для целых чисел. В частности, вы можете использовать Int32, Int64 для определения 32- или 64-битного целого числа со знаком, тогда как UInt32 или UInt64 для определения 32- или 64-битных целочисленных переменных без знака. Например, 42 и -23.

  • Float- Используется для представления 32-битного числа с плавающей запятой и чисел с меньшими десятичными точками. Например, 3,14159, 0,1 и -273,158.

  • Double- Используется для представления 64-битного числа с плавающей запятой и используется, когда значения с плавающей запятой должны быть очень большими. Например, 3,14159, 0,1 и -273,158.

  • Bool - Представляет логическое значение, которое может быть истинным или ложным.

  • String- Это упорядоченный набор персонажей. Например, «Привет, мир!»

  • Character- Это односимвольный строковый литерал. Например, «С»

  • Optional - Это представляет собой переменную, которая может содержать значение или не иметь значения.

  • Tuples - Используется для группировки нескольких значений в одно составное значение.

Мы перечислили здесь несколько важных моментов, связанных с целочисленными типами:

  • На 32-битной платформе Int имеет тот же размер, что и Int32.

  • На 64-битной платформе Int имеет тот же размер, что и Int64.

  • На 32-битной платформе UInt имеет тот же размер, что и UInt32.

  • На 64-битной платформе UInt имеет тот же размер, что и UInt64.

  • Int8, Int16, Int32, Int64 могут использоваться для представления 8-битных, 16-битных, 32-битных и 64-битных форм целого числа со знаком.

  • UInt8, UInt16, UInt32 и UInt64 могут использоваться для представления 8-битных, 16-битных, 32-битных и 64-битных форм целых чисел без знака.

Связанные значения

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

Тип Типичная битовая ширина Типичный диапазон
Int8 1 байт От -127 до 127
UInt8 1 байт От 0 до 255
Int32 4 байта От -2147483648 до 2147483647
UInt32 4 байта 0 на 4294967295
Int64 8 байтов От -9223372036854775808 до 9223372036854775807
UInt64 8 байтов 0 по 18446744073709551615
Плавать 4 байта От 1.2E-38 до 3.4E + 38 (~ 6 цифр)
Двойной 8 байтов 2.3E-308 до 1.7E + 308 (~ 15 цифр)

Псевдонимы типов

Вы можете создать новое имя для существующего типа, используя typealias. Вот простой синтаксис для определения нового типа с использованием typealias -

typealias newname = type

Например, следующая строка указывает компилятору, что Feet другое название для Int -

typealias Feet = Int

Теперь следующее объявление совершенно законно и создает целочисленную переменную с именем distance -

typealias Feet = Int
var distance: Feet = 100
print(distance)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат.

100

Тип Безопасность

Swift 4 - это типобезопасный язык, что означает, что если часть вашего кода ожидает String, вы не можете передать ей Int по ошибке.

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

var varA = 42
varA = "This is hello"
print(varA)

Когда мы компилируем вышеуказанную программу, она выдает следующую ошибку времени компиляции.

main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"

Вывод типа

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

// varA is inferred to be of type Int
var varA = 42
print(varA)

// varB is inferred to be of type Double
var varB = 3.14159
print(varB)

// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

42
3.14159
3.14159

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

Swift 4 поддерживает следующие основные типы переменных:

  • Int or UInt- Используется для целых чисел. В частности, вы можете использовать Int32, Int64 для определения 32- или 64-битного целого числа со знаком, тогда как UInt32 или UInt64 для определения 32- или 64-битных целочисленных переменных без знака. Например, 42 и -23.

  • Float- Используется для представления 32-битного числа с плавающей запятой. Он используется для хранения чисел с меньшей десятичной точкой. Например, 3,14159, 0,1 и -273,158.

  • Double- Используется для представления 64-битного числа с плавающей запятой и используется, когда значения с плавающей запятой должны быть очень большими. Например, 3.14159, 0.1 и -273.158.

  • Bool - Представляет логическое значение, которое может быть истинным или ложным.

  • String- Это упорядоченный набор персонажей. Например, «Привет, мир!»

  • Character- Это односимвольный строковый литерал. Например, «С»

Swift 4 также позволяет определять различные другие типы переменных, которые мы рассмотрим в следующих главах, например Optional, Array, Dictionaries, Structures, и Classes.

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

Объявление переменной

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

var variableName = <initial value>

В следующем примере показано, как объявить переменную в Swift 4 -

var varA = 42
print(varA)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

42

Аннотации типов

Вы можете предоставить type annotationкогда вы объявляете переменную, чтобы иметь четкое представление о том, какие значения может хранить переменная. Вот синтаксис -

var variableName:<data type> = <optional initial value>

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

var varA = 42
print(varA)

var varB:Float

varB = 3.14159
print(varB)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

42
3.1415901184082

Именование переменных

Имя переменной может состоять из букв, цифр и символа подчеркивания. Он должен начинаться с буквы или символа подчеркивания. Прописные и строчные буквы различаются, потому что Swift 4 - это язык программирования с учетом регистра.

Вы можете использовать простые символы или символы Unicode для именования переменных. В следующих примерах показано, как вы можете назвать переменные -

var _var = "Hello, Swift 4!"
print(_var)

var 你好 = "你好世界"
print(你好)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат.

Hello, Swift 4!
你好世界

Печать переменных

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

var varA = "Godzilla"
var varB = 1000.00

print("Value of \(varA) is more than \(varB) millions")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат.

Value of Godzilla is more than 1000.0 millions

Swift 4 также представляет Optionalstype, который обрабатывает отсутствие значения. Необязательные параметры говорят либо «есть значение, и оно равно x», либо «нет значения вообще».

Optional - это отдельный тип, фактически одно из новых сверхмощных перечислений Swift 4. У него есть два возможных значения:None и Some(T), где T - это связанное значение правильного типа данных, доступного в Swift 4.

Вот необязательное объявление Integer -

var perhapsInt: Int?

Вот необязательное объявление String -

var perhapsStr: String?

Приведенное выше объявление эквивалентно явной инициализации его как nil что означает отсутствие ценности -

var perhapsStr: String? = nil

Давайте рассмотрим следующий пример, чтобы понять, как опции работают в Swift 4:

var myString:String? = nil

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

myString has nil value

Варианты аналогичны использованию nil с указателями в Objective-C, но они работают для любого типа, а не только для классов.

Принудительная распаковка

Если вы определили переменную как optional, то чтобы получить значение из этой переменной, вам нужно будет unwrapЭто. Это означает просто поставить восклицательный знак в конце переменной.

Возьмем простой пример -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Optional("Hello, Swift 4!")

Теперь давайте применим разворачивание, чтобы получить правильное значение переменной -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print( myString! )
} else {
   print("myString has nil value")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат.

Hello, Swift 4!

Автоматическая распаковка

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

var myString:String!
myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Hello, Swift 4!

Необязательная привязка

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

Необязательная привязка для if заявление выглядит следующим образом -

if let constantName = someOptional {
   statements
}

Давайте рассмотрим простой пример, чтобы понять использование необязательной привязки -

var myString:String?
myString = "Hello, Swift 4!"

if let yourString = myString {
   print("Your string has - \(yourString)")
} else {
   print("Your string does not have a value")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Your string has - Hello, Swift 4!

Swift 4 также представляет Tuples type, которые используются для группировки нескольких значений в одно составное значение.

Значения в кортеже могут быть любого типа и не обязательно должны быть одного типа.

Например, («Tutorials Point», 123) - это кортеж с двумя значениями, одно из которых имеет строковый тип, а другое - целочисленный. Это законная команда.

let ImplementationError = (501, «Не реализовано») - это ошибка, когда что-то на сервере не реализовано. Возвращает два значения. Код ошибки и описание.

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

Вот синтаксис объявления Tuple -

var TupleName = (Value1, value2,… any number of values)

Вот объявление Tuple -

var error501 = (501, “Not implemented”)

Вы можете получить доступ к значениям кортежа, используя номера индексов, начинающиеся с 0.

Вот пример доступа к значениям кортежа -

print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)

Вы можете назвать переменные кортежа при объявлении, и вы можете вызывать их, используя их имена

var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode)   // prints 501.

Кортежи полезны при возврате нескольких значений из функции. Например, веб-приложение может возвращать кортеж типа ("String", Int), чтобы показать, была ли загрузка успешной или неудачной.

Возвращая разные значения в кортеж, мы можем принимать решения в зависимости от разных типов кортежей.

Note - Кортежи полезны для временных значений и не подходят для сложных данных.

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

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

Объявление констант

Прежде чем использовать константы, вы должны объявить их, используя let ключевое слово следующим образом -

let constantName = <initial value>

Ниже приведен простой пример, показывающий, как объявить константу в Swift 4.

let constA = 42
print(constA)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

42

Аннотации типов

Вы можете предоставить type annotationкогда вы объявляете константу, чтобы понять, какие значения она может хранить. Ниже приводится синтаксис -

var constantName:<data type> = <optional initial value>

В следующем примере показано, как объявить константу в Swift 4 с помощью аннотации. Здесь важно отметить, что при создании константы обязательно указать начальное значение -

let constA = 42
print(constA)

let constB:Float = 3.14159
print(constB)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат.

42
3.1415901184082

Константы именования

Имя константы может состоять из букв, цифр и символа подчеркивания. Он должен начинаться с буквы или символа подчеркивания. Прописные и строчные буквы различаются, потому что Swift 4 - это язык программирования с учетом регистра.

Вы можете использовать простые символы или символы Unicode для именования переменных. Ниже приведены действительные примеры -

let _const = "Hello, Swift 4!"
print(_const)

let 你好 = "你好世界"
print(你好)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Hello, Swift 4!
你好世界

Константы печати

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

let constA = "Godzilla"
let constB = 1000.00

print("Value of \(constA) is more than \(constB) millions")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Value of Godzilla is more than 1000.0 millions

Литерал - это представление исходного кода значения целого числа, числа с плавающей запятой или строкового типа. Ниже приведены примеры литералов -

42                // Integer literal
3.14159           // Floating-point literal
"Hello, world!"   // String literal

Целочисленные литералы

Целочисленный литерал может быть десятичной, двоичной, восьмеричной или шестнадцатеричной константой. Двоичные литералы начинаются с 0b, восьмеричные литералы начинаются с 0o, а шестнадцатеричные литералы начинаются с 0x и ничего для десятичных.

Вот несколько примеров целочисленных литералов -

let decimalInteger = 17         // 17 in decimal notation
let binaryInteger = 0b10001     // 17 in binary notation
let octalInteger = 0o21         // 17 in octal notation
let hexadecimalInteger = 0x11   // 17 in hexadecimal notation

Литералы с плавающей точкой

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

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

Шестнадцатеричные литералы с плавающей запятой состоят из префикса 0x, за которым следует необязательная шестнадцатеричная дробь, за которой следует шестнадцатеричный показатель степени.

Вот несколько примеров литералов с плавающей запятой -

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

Строковые литералы

Строковый литерал - это последовательность символов, окруженная двойными кавычками, имеющая следующую форму:

"characters"

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

Последовательность выхода Имея в виду
\ 0 Нулевой символ
\\ \персонаж
\ b Backspace
\ f Подача формы
\ п Новая линия
Возврат каретки
\ т Горизонтальная вкладка
\ v Вертикальная табуляция
\ ' Одиночная цитата
\ " Двойная кавычка
\ 000 Восьмеричное число от одной до трех цифр
\ ххх ... Шестнадцатеричное число из одной или нескольких цифр

В следующем примере показано, как использовать несколько строковых литералов -

let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Hello World

Hello'Swift 4'

Логические литералы

Есть три логических литерала, и они являются частью стандартных ключевых слов Swift 4 -

  • Ценность true представляющий истину.

  • Ценность false представляющий ложь.

  • Ценность nil не представляющий никакой ценности.

Оператор - это символ, который сообщает компилятору о необходимости выполнения определенных математических или логических операций. Objective-C богат встроенными операторами и предоставляет следующие типы операторов:

  • Арифметические операторы
  • Операторы сравнения
  • Логические операторы
  • Побитовые операторы
  • Операторы присваивания
  • Операторы диапазона
  • Разные операторы

В этом руководстве поочередно будут объяснены арифметические, реляционные, логические, побитовые, присваивающие и другие операторы.

Арифметические операторы

В следующей таблице показаны все арифметические операторы, поддерживаемые языком Swift 4. Предположим переменнуюA содержит 10 и переменную B держит 20, то -

Оператор Описание пример
+ Добавляет два операнда A + B даст 30
- Вычитает второй операнд из первого A - B даст -10
* Умножает оба операнда A * B даст 200
/ Делит числитель на знаменатель Б / А даст 2
% Оператор модуля и остаток после деления целого числа на число с плавающей запятой B% A даст 0

Операторы сравнения

В следующей таблице показаны все операторы отношения, поддерживаемые языком Swift 4. Предположим переменнуюA содержит 10 и переменную B держит 20, то -

Оператор Описание пример
== Проверяет, равны ли значения двух операндов; если да, то условие выполняется. (A == B) неверно.
знак равно Проверяет, равны ли значения двух операндов; если значения не равны, то условие становится истинным. (A! = B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда; если да, то условие выполняется. (A> B) неверно.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда; если да, то условие выполняется. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда; если да, то условие выполняется. (A> = B) неверно.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда; если да, то условие выполняется. (A <= B) верно.

Логические операторы

В следующей таблице показаны все логические операторы, поддерживаемые языком Swift 4. Предположим переменнуюA содержит 1 и переменную B имеет 0, то -

Оператор Описание пример
&& Вызывается логическим оператором И. Если оба операнда ненулевые, условие становится истинным. (A && B) ложно.
|| Вызывается логическим оператором ИЛИ. Если какой-либо из двух операндов не равен нулю, условие становится истинным. (A || B) верно.
! Вызывается оператором логического НЕ. Используется для изменения логического состояния операнда на обратное. Если условие истинно, то оператор логического НЕ сделает его ложным. ! (A && B) верно.

Побитовые операторы

Побитовые операторы работают с битами и выполняют побитовую операцию. Таблицы истинности для &, | и ^ следующие:

п q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
Assume A = 60; and B = 13;

In binary format, they will be as follows:

A = 0011 1100

B = 0000 1101

-----------------

A & B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

Побитовые операторы, поддерживаемые языком Swift 4, перечислены в следующей таблице. Предположим переменнуюA содержит 60 и переменную B выполняется 13, то 7−

Оператор Описание пример
& Двоичный оператор И копирует бит в результат, если он существует в обоих операндах. (A и B) даст 12, что составляет 0000 1100
| Оператор двоичного ИЛИ копирует бит, если он существует в любом из операндов. (A | B) даст 61, то есть 0011 1101
^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) даст 49, что составляет 0011 0001
~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~ A) даст -61, что составляет 1100 0011 в форме дополнения до 2.
<< Оператор двоичного сдвига влево. Значение левого операнда сдвигается влево на количество битов, указанное правым операндом. (<< 2 даст 240, что составляет 1111 0000
>> Оператор двоичного сдвига вправо. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 даст 15, что равно 0000 1111

Операторы присваивания

SSwift 4 поддерживает следующие операторы присваивания -

Оператор Описание пример
знак равно Простой оператор присваивания, присваивает значения из правых операндов левому операнду C = A + B присвоит значение A + B в C
+ = Добавить оператор присваивания И, он добавляет правый операнд к левому операнду и присваивает результат левому операнду C + = A эквивалентно C = C + A
знак равно Оператор вычитания И присваивания, он вычитает правый операнд из левого операнда и присваивает результат левому операнду C - = A эквивалентно C = C - A
знак равно Оператор умножения И присваивания, он умножает правый операнд на левый операнд и присваивает результат левому операнду C * = A эквивалентно C = C * A
знак равно Оператор деления И присваивания, он делит левый операнд на правый операнд и присваивает результат левому операнду C / = A эквивалентно C = C / A
знак равно Оператор модуля И присваивания, принимает модуль с использованием двух операндов и присваивает результат левому операнду C% = A эквивалентно C = C% A
<< = Левый сдвиг И оператор присваивания C << = 2 совпадает с C = C << 2
>> = Оператор сдвига вправо И присваивания C >> = 2 совпадает с C = C >> 2
знак равно Побитовый оператор присваивания И C & = 2 совпадает с C = C & 2
^ = побитовое исключающее ИЛИ и оператор присваивания C ^ = 2 совпадает с C = C ^ 2
| = побитовое включающее ИЛИ и оператор присваивания C | = 2 совпадает с C = C | 2

Операторы диапазона

Swift 4 включает в себя два оператора диапазона, которые являются ярлыками для выражения диапазона значений. В следующей таблице объясняются эти два оператора.

Оператор Описание пример
Закрытый диапазон (a ... b) определяет диапазон от a до b и включает значения a и b. 1 ... 5 дает 1, 2, 3, 4 и 5
Полуоткрытый диапазон (a .. <b) определяет диапазон от a до b, но не включает b. 1 .. <5 дает 1, 2, 3 и 4
Односторонний диапазон

a…, определяет диапазон от одного до конца элементов.

… A, определяет диапазон от начала до

1… дает 1, 2,3… конец элементов

… 2 дает начало… 1,2

Разные операторы

Swift 4 поддерживает несколько других важных операторов, включая rangeи ? : которые объяснены в следующей таблице.

Оператор Описание пример
Унарный минус Знак числового значения можно переключать с помощью префикса - -3 или -4
Унарный Плюс Возвращает значение, с которым работает, без каких-либо изменений. +6 дает 6
Тернарный условный Состояние ? X: Y Если условие верно? Затем значение X: в противном случае значение Y

Приоритет операторов

Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения.

Например, x = 7 + 3 * 2; здесь x присваивается 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем складывается в 7.

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

Оператор Описание пример
Операторы первичного выражения () []. expr ++ expr-- слева направо
Унарные операторы

* & + -! ~ ++ выражение - выражение

* /%

+ -

>> <<

<> <=> =

==! =

справа налево
Бинарные операторы

&

^

|

&&

||

слева направо
Тернарный оператор ?: справа налево
Операторы присваивания = + = - = * = / =% = >> = << = & = ^ = | = справа налево
Запятая , слева направо

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

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

Swift 4 предоставляет следующие типы заявлений о принятии решений. Щелкните следующие ссылки, чтобы проверить их детали.

Старший Нет Заявление и описание
1 если заявление

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

2 если ... еще заявление

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

3 if ... else if ... else Заявление

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

4 вложенные операторы if

Вы можете использовать один оператор if или else if внутри другого оператора if или else if.

5 оператор переключения

Оператор switch позволяет проверять переменную на равенство со списком значений.

? : Оператор

Мы покрыли conditional operator ? : в предыдущей главе, которые можно использовать для замены if...elseзаявления. Он имеет следующий общий вид -

Exp1 ? Exp2 : Exp3;

Где Exp1, Exp2 и Exp3 - выражения. Обратите внимание на использование и размещение двоеточия.

Значение? выражение определяется следующим образом: вычисляется Exp1. Если это правда, то Exp2 оценивается и становится значением всего? выражение. Если Exp1 ложно, то вычисляется Exp3, и его значение становится значением выражения.

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

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

Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз. Ниже приводится общий из оператора цикла в большинстве языков программирования.

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

Старший Нет Тип и описание петли
1 за-в

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

2 пока цикл

Повторяет утверждение или группу утверждений, пока выполняется заданное условие. Он проверяет условие перед выполнением тела цикла.

3 повторить ... пока цикл

Подобен оператору while, за исключением того, что он проверяет условие в конце тела цикла.

Заявления контроля цикла

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

Swift 4 поддерживает следующие управляющие операторы. Щелкните следующие ссылки, чтобы проверить их детали.

Старший Нет Положение и описание управления
1 продолжить заявление

Этот оператор сообщает циклу, чтобы он остановил свои действия и начал снова в начале следующей итерации цикла.

2 заявление о прерывании

Завершает оператор цикла и передает выполнение оператору, непосредственно следующему за циклом.

3 заявление о провале

Оператор fallthrough имитирует поведение переключения Swift 4 на переключатель стиля C.

Строки в Swift 4 представляют собой упорядоченный набор символов, например «Hello, World!» и они представлены типом данных Swift 4String, который, в свою очередь, представляет собой набор значений Character тип.

Создать строку

Вы можете создать String, используя строковый литерал или создав экземпляр класса String следующим образом:

// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )

// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )

//Multiple line string

let stringC = """
Hey this is a
example of multiple Line
string by tutorialsPoint 

"""
print(stringC)

Когда приведенный выше код компилируется и выполняется, он дает следующий результат

Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by tutorialsPoint

Пустой строкой

Вы можете создать пустую строку, используя пустой строковый литерал или создав экземпляр класса String, как показано ниже. Вы также можете проверить, пуста ли строка или нет, используя свойство BooleanisEmpty.

// Empty string creation using String literal
var stringA = ""

if stringA.isEmpty {
   print( "stringA is empty" )
} else {
   print( "stringA is not empty" )
}

// Empty string creation using String instance
let stringB = String()

if stringB.isEmpty {
   print( "stringB is empty" )
} else {
   print( "stringB is not empty" )
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

stringA is empty
stringB is empty

Строковые константы

Вы можете указать, может ли ваша строка быть изменена (или видоизменена), назначив ее переменной, или она будет постоянной, назначив ее константе, используя let ключевое слово, как показано ниже -

// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )

// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"

Строчная интерполяция

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

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

var varA = 20
let constA = 100
var varC:Float = 20.0

var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

20 times 100 is equal to 2000.0

Конкатенация строк

Вы можете использовать оператор + для объединения двух строк или строки и символа или двух символов. Вот простой пример -

let constA = "Hello,"
let constB = "World!"

var stringA = constA + constB
print( stringA )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Hello,World!

Длина строки

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

var varA = "Hello, Swift 4!"

print( "\(varA), length is \((varA.count))" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Hello, Swift 4!, length is 15

Сравнение строк

Вы можете использовать оператор == для сравнения двух строковых переменных или констант. Вот простой пример -

var varA = "Hello, Swift 4!"
var varB = "Hello, World!"

if varA == varB {
   print( "\(varA) and \(varB) are equal" )
} else {
   print( "\(varA) and \(varB) are not equal" )
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Hello, Swift 4! and Hello, World! are not equal

Итерация строки

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

for chars in "ThisString" {
   print(chars, terminator: " ")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

T h i s S t r i n g

Строки Юникода

Вы можете получить доступ к UTF-8 и UTF-16 представлению String, перебирая его свойства utf8 и utf16, как показано в следующем примере:

var unicodeString = "Dog???"

print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
   print("\(code) ")
}

print("\n")

print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
   print("\(code) ")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

UTF-8 Codes: 
68 
111 
103 
63 
63 
63 


UTF-16 Codes: 
68 
111 
103 
63 
63 
63

Строковые функции и операторы

Swift 4 поддерживает широкий спектр методов и операторов, связанных со строками -

Старший Нет Функции / Операторы и цель
1

isEmpty

Логическое значение, определяющее, пуста строка или нет.

2

hasPrefix(prefix: String)

Функция для проверки, существует ли данная строка параметра как префикс строки или нет.

3

hasSuffix(suffix: String)

Функция для проверки, существует ли данная строка параметра как суффикс строки или нет.

4

toInt()

Функция для преобразования числового значения String в Integer.

5

count()

Глобальная функция для подсчета количества символов в строке.

6

utf8

Свойство, возвращающее представление строки в кодировке UTF-8.

7

utf16

Свойство, возвращающее представление строки в кодировке UTF-16.

8

unicodeScalars

Свойство для возврата скалярного представления строки в Юникоде.

9

+

Оператор для объединения двух строк, или строки и символа, или двух символов.

10

+=

Оператор для добавления строки или символа к существующей строке.

11

==

Оператор для определения равенства двух строк.

12

<

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

13

startIndex

Чтобы получить значение в начальном индексе строки.

14

endIndex

Чтобы получить значение в конце индекса строки.

15

Indices

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

16

insert("Value", at: position)

Чтобы вставить значение в позицию.

17

remove(at: position)

removeSubrange(range)

для удаления значения в позиции или для удаления диапазона значений из строки.

18

reversed()

возвращает обратную сторону строки

А character в Swift - это односимвольный строковый литерал, адресованный типом данных Character. Взгляните на следующий пример. Он использует две символьные константы -

let char1: Character = "A"
let char2: Character = "B"

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of char1 A
Value of char2 B

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

// Following is wrong in Swift 4
let char: Character = "AB"

print("Value of char \(char)")

Пустые символьные переменные

Невозможно создать пустую символьную переменную или константу, которая будет иметь пустое значение. Следующий синтаксис невозможен -

// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

Доступ к символам из строк

Как объяснялось при обсуждении строк Swift 4, String представляет собой набор значений символов в указанном порядке. Таким образом, мы можем получить доступ к отдельным символам из данной строки, перебирая эту строку с помощьюfor-in петля -

for ch in "Hello" {
   print(ch)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

H
e
l
l
o

Объединение строк с символами

В следующем примере показано, как персонаж Swift 4 может быть объединен со строкой Swift 4.

var varA:String = "Hello "
let varB:Character = "G"

varA.append( varB )

print("Value of varC = \(varA)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of varC = Hello G

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

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

Создание массивов

Вы можете создать пустой массив определенного типа, используя следующий синтаксис инициализатора -

var someArray = [SomeType]()

Вот синтаксис для создания массива заданного размера a * и инициализации его значением -

var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)

Вы можете использовать следующий оператор для создания пустого массива Int тип, имеющий 3 элемента и начальное значение как ноль -

var someInts = [Int](count: 3, repeatedValue: 0)

Ниже приведен еще один пример создания массива из трех элементов и присвоения ему трех значений.

var someInts:[Int] = [10, 20, 30]

Доступ к массивам

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

var someVar = someArray[index]

Здесь indexначинается с 0, что означает, что к первому элементу можно получить доступ, используя индекс как 0, ко второму элементу можно получить доступ, используя индекс как 1 и так далее. В следующем примере показано, как создавать, инициализировать и получать доступ к массивам.

var someInts = [Int](count: 3, repeatedValue: 10)

var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of first element is 10
Value of second element is 10
Value of third element is 10

Изменение массивов

Вы можете использовать append()метод или оператор присваивания сложения (+ =), чтобы добавить новый элемент в конец массива. Взгляните на следующий пример. Здесь сначала мы создаем пустой массив, а затем добавляем новые элементы в тот же массив -

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of first element is 20
Value of second element is 30
Value of third element is 40

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

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

// Modify last element
someInts[2] = 50

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of first element is 20
Value of second element is 30
Value of third element is 50

Итерация по массиву

Вы можете использовать for-in цикл для перебора всего набора значений в массиве, как показано в следующем примере:

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
   print(item)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Apple
Amazon
Google

Вы можете использовать enumerate() функция, которая возвращает индекс элемента вместе с его значением, как показано ниже в следующем примере -

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]

for (index, item) in someStrs.enumerated() {
   print("Value at index = \(index) is \(item)")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

Добавление двух массивов

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

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB
for item in intsC {
   print(item)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

2
2
1
1
1

Граф собственности

Вы можете использовать только для чтения count свойство массива, чтобы узнать количество элементов в массиве, показанном ниже -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB

print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5

Пустое свойство

Вы можете использовать только для чтения empty свойство массива, чтобы узнать, пуст ли массив или нет, как показано ниже -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()

print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true

Swift 4 sets используются для хранения различных значений одного и того же типа, но у них нет определенного порядка, как в массивах.

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

Тип должен быть хешируемым, чтобы храниться в наборе. Хеш-значение - это значение типа Int, равное для одинаковых объектов. Например, если x == y, тоx.hashvalue == y.hashvalue.

Все базовые значения swift по умолчанию имеют хешируемый тип и могут использоваться в качестве установленных значений.

Создание наборов

Вы можете создать пустой набор определенного типа, используя следующий синтаксис инициализатора -

var someSet = Set<Character>()     //Character can be replaced by data type of set.

Доступ и изменение наборов

Вы можете получить доступ или изменить набор, используя его методы и свойства -

Метод "count" можно использовать для отображения количества элементов в наборе.

someSet.count        // prints the number of elements

Метод "вставки" может использоваться для вставки значений в набор.

someSet.insert("c")   // adds the element to Set.

Точно так же isEmpty можно использовать для проверки, пусто ли set.

someSet.isEmpty       // returns true or false depending on the set Elements.

Метод "remove" может использоваться для удаления значения в наборе.

someSet.remove("c")     // removes a element , removeAll() can be used to remove all elements

Метод "contains" может использоваться для проверки наличия значения в наборе.

someSet.contains("c")     // to check if set contains this value.

Итерация по набору

Вы можете перебирать набор, используя цикл for-in -

for items in someSet {
   print(someSet)
}

//Swift sets are not in an ordered way, to iterate over a set in ordered way use

for items in someSet.sorted() {
   print(someSet)
}

Выполнение операций над наборами

Вы можете выполнять базовые операции над наборами на быстрых наборах.

Ниже приведены методы выполнения установленных операций -

  • Intersection
  • Union
  • subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]

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

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

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

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

Создание словаря

Вы можете создать пустой словарь определенного типа, используя следующий синтаксис инициализатора -

var someDict = [KeyType: ValueType]()

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

var someDict = [Int: String]()

Вот пример создания словаря из набора заданных значений -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

Инициализация на основе последовательности

Swift 4 позволяет создавать словарь из массивов (пары ключ-значение).

var cities = [“Delhi”,”Bangalore”,”Hyderabad”]

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

var Distance = [2000,10, 620]

Вот пример создания словаря из набора заданных значений -

let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))

Приведенные выше строки кода создадут словарь с городами в качестве ключа и расстоянием в качестве значения -

Фильтрация

Swift 4 позволяет фильтровать значения из словаря.

var closeCities = cityDistanceDict.filter { $0.value < 1000 }

Если мы запустим приведенный выше код, наш словарь closeCities будет.

["Bangalore" : 10 , "Hyderabad" : 620]

Группировка словаря

Swift 4 позволяет создавать группировку значений словаря.

var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]

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

var GroupedCities = Dictionary(grouping: cities ) { $0.first! }

Результатом приведенного выше кода будет

["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]

Доступ к словарям

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

var someVar = someDict[key]

Давайте проверим следующий пример для создания, инициализации и доступа к значениям из словаря:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]

print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

Изменение словарей

Вы можете использовать updateValue(forKey:)для добавления существующего значения к заданному ключу словаря. Этот метод возвращает необязательное значение типа значения словаря. Вот простой пример -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

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

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

Удалить пары ключ-значение

Вы можете использовать removeValueForKey()для удаления пары ключ-значение из словаря. Этот метод удаляет пару "ключ-значение", если она существует, и возвращает удаленное значение, или возвращает ноль, если значение не существовало. Вот простой пример -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

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

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

someDict[2] = nil

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

Итерация по словарю

Вы можете использовать for-in цикл для перебора всего набора пар ключ-значение в Словаре, как показано в следующем примере:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

for (index, keyValue) in someDict.enumerated() {
   print("Dictionary key \(index) - Dictionary value \(keyValue)")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One

Вы можете использовать enumerate() функция, которая возвращает индекс элемента вместе с его парой (ключ, значение), как показано ниже в примере -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
   print("Dictionary key \(key) - Dictionary value \(value)")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")

Преобразовать в массивы

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

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)

print("Print Dictionary Keys")

for (key) in dictKeys {
   print("\(key)")
}
print("Print Dictionary Values")

for (value) in dictValues {
   print("\(value)")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One

Граф собственности

Вы можете использовать только для чтения count свойство словаря, чтобы узнать количество элементов в словаре, как показано ниже -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]

print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Total items in someDict1 = 3
Total items in someDict2 = 2

Пустое свойство

Вы можете использовать только для чтения empty свойство словаря, чтобы узнать, пустой словарь или нет, как показано ниже -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()

print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

someDict1 = false
someDict2 = false
someDict3 = true

Функция - это набор операторов, организованных вместе для выполнения определенной задачи. Функция Swift 4 может быть настолько простой, как простая функция C, так и сложной, как функция языка Objective C. Это позволяет нам передавать значения локальных и глобальных параметров внутри вызовов функций.

  • Function Declaration - сообщает компилятору имя функции, тип возвращаемого значения и параметры.

  • Function Definition - Он обеспечивает фактическое тело функции.

Функции Swift 4 содержат тип параметра и его возвращаемые типы.

Определение функции

В Swift 4 функция определяется ключевым словом func. Когда функция определяется заново, она может принимать одно или несколько значений в качестве входных «параметров» функции, и она будет обрабатывать функции в основном теле и передавать значения функциям в качестве выходных «возвращаемых типов».

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

Аргументы функции всегда должны предоставляться в том же порядке, что и список параметров функции, а за возвращаемыми значениями следует знак →.

Синтаксис

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

Взгляните на следующий код. Имя студента объявляется как строковый тип данных, объявленный внутри функции «student», и при вызове функции она возвращает имя студента.

func student(name: String) -> String {
   return name
}

print(student(name: "First Program"))
print(student(name: "About Functions"))

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

First Program
About Functions

Вызов функции

Предположим, мы определили функцию с именем 'display' для рассмотрения, например, для отображения чисел функция с именем функции 'display' инициализируется первой с аргументом 'no1', который содержит целочисленный тип данных. Затем аргумент «no1» присваивается аргументу «a», который в дальнейшем будет указывать на тот же тип данных целое число. Теперь в функцию возвращается аргумент «а». Здесь функция display () будет хранить целочисленное значение и возвращать целочисленные значения при каждом вызове функции.

func display(no1: Int) -> Int {
   let a = no1
   return a
}

print(display(no1: 100))
print(display(no1: 200))

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -

100
200

Параметры и возвращаемые значения

Swift 4 предоставляет гибкие параметры функции и ее возвращаемые значения от простых до сложных значений. Подобно функциям C и Objective C, функции в Swift 4 также могут принимать несколько форм.

Функции с параметрами

Доступ к функции осуществляется путем передачи значений ее параметров в тело функции. Мы можем передавать одно или несколько значений параметров в виде кортежей внутри функции.

func mult(no1: Int, no2: Int) -> Int {
   return no1*no2
}

print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат -

40
45
120

Функции без параметров

У нас также могут быть функции без параметров.

Синтаксис

func funcname() -> datatype {
   return datatype
}

Ниже приведен пример функции без параметра -

func votersname() -> String {
   return "Alice"
}
print(votersname())

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Alice

Функции с возвращаемыми значениями

Функции также используются для возврата значений строковых, целочисленных и плавающих типов данных в качестве возвращаемых типов. Чтобы узнать наибольшее и наименьшее число в заданном массиве, объявляется функция ls с типами данных big и small целочисленные.

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

func ls(array: [Int]) -> (large: Int, small: Int) {
   var lar = array[0]
   var sma = array[0]

   for i in array[1..<array.count] {
      if i < sma {
         sma = i
      } else if i > lar {
         lar = i
      }
   }
   return (lar, sma)
}

let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Largest number is: 98 and smallest number is: -5

Функции без возвращаемых значений

Некоторые функции могут иметь аргументы, объявленные внутри функции, без каких-либо возвращаемых значений. Следующая программа объявляетa и bв качестве аргументов функции sum (). внутри самой функции значения аргументовa и b передаются путем вызова функции sum (), и ее значения печатаются, тем самым устраняя возвращаемые значения.

func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

30 20
50 40
30 24

Функции с дополнительными типами возврата

Swift 4 представляет «необязательную» функцию, позволяющую избавиться от проблем с помощью меры безопасности. Рассмотрим, например, что мы объявляем тип возвращаемого значения функции как целое число, но что произойдет, когда функция вернет строковое значение или либо значение nil. В этом случае компилятор вернет значение ошибки. «необязательные» вводятся, чтобы избавиться от этих проблем.

Необязательные функции могут принимать две формы: «значение» и «ноль». Мы упомянем «Optionals» с ключевым зарезервированным символом «?» чтобы проверить, возвращает ли кортеж значение или нулевое значение.

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var currentMin = array[0]
   var currentMax = array[0]
   
   for value in array[1..<array.count] {
      if value < currentMin {
         currentMin = value
      } else if value > currentMax {
         currentMax = value
      }
   }
   return (currentMin, currentMax)
}

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
   print("min is \(bounds.min) and max is \(bounds.max)")
}

Когда мы запускаем вышеуказанную программу с использованием игровой площадки, мы получаем следующий результат -

min is -6 and max is 109

«Необязательные» используются для проверки значений «nil» или «мусора», что отнимает много времени на отладку и делает код эффективным и читаемым для пользователя.

Функции Локальные и внешние имена параметров

Имена локальных параметров

Имена локальных параметров доступны только внутри функции.

func sample(number: Int) {
   print(number)
}

Здесь funcНомер аргумента sample объявлен как внутренняя переменная, поскольку к нему обращается внутренняя функция sample (). Здесь 'число' объявлено как локальная переменная, но ссылка на переменную делается вне функции с помощью следующего оператора:

func sample(number: Int) {
   print(number)
}

sample(number: 1)
sample(number: 2)
sample(number: 3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

1
2
3

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

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

func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}

pow(firstArg:5, secondArg:3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

125

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

Когда мы хотим определить функцию с несколькими аргументами, мы можем объявить члены как «вариативные» параметры. Параметры могут быть указаны как переменные с помощью (···) после имени параметра.

func vari<N>(members: N...){
   for i in members {
      print(i)
   }
}

vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures

Постоянные, переменные и параметры ввода / вывода

Функции по умолчанию рассматривают параметры как «постоянные», тогда как пользователь может также объявлять аргументы функций как переменные. Мы уже обсуждали, что ключевое слово let используется для объявления постоянных параметров, а параметры переменных определяются с помощью ключевого слова var.

Параметры ввода-вывода в Swift 4 предоставляют функциональные возможности для сохранения значений параметров, даже если их значения изменяются после вызова функции. В начале определения параметра функции объявляется ключевое слово inout для сохранения значений членов.

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

Переменные передаются только в качестве аргумента для параметра in-out, поскольку только его значения изменяются внутри и вне функции. Следовательно, нет необходимости объявлять строки и литералы в качестве входных-выходных параметров. Символ «&» перед именем переменной указывает на то, что мы передаем аргумент параметру входа-выхода.

func temp(a1: inout Int, b1: inout Int) {
   let t = a1
   a1 = b1
   b1 = t
}

var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swapped values are 10, 2

Типы функций и их использование

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

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

Ниже приведен пример -

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

2
6

Здесь функция инициализируется двумя аргументами no1 и no2 как целочисленные типы данных и его возвращаемый тип также объявлен как int

Func inputstr(name: String) -> String {
   return name
}

Здесь функция объявлена ​​как string тип данных.

Функции также могут иметь void типы данных и такие функции ничего не вернут.

func inputstr() {
   print("Swift 4 Functions")
   print("Types and its Usage")
}
inputstr()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swift 4 Functions
Types and its Usage

Вышеупомянутая функция объявлена ​​как функция void без аргументов и без возвращаемых значений.

Использование типов функций

Функции сначала передаются с аргументами целочисленного, плавающего или строкового типа, а затем передаются функции как константы или переменные, как указано ниже.

var addition: (Int, Int) -> Int = sum

Здесь sum - это имя функции, имеющее целочисленные переменные 'a' и 'b', которое теперь объявлено как переменная к добавлению имени функции. В дальнейшем и сложение, и функция суммы имеют одинаковое количество аргументов, объявленных как целочисленный тип данных, а также возвращают целые значения в качестве ссылок.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Result: 129

Типы функций как типы параметров и типы возврата

Мы также можем передать саму функцию как типы параметров другой функции.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
   print("Result: \(addition(a, b))")
}
another(sum, 10, 20)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Result: 129
Result: 30

Вложенные функции

Вложенная функция обеспечивает возможность вызова внешней функции путем вызова внутренней функции.

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 0
   func decrementer() -> Int {
      overallDecrement -= total
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 30)
print(decrem())

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

-30

Замыкания в Swift 4 похожи на замыкания автономных функций, организованных в виде блоков и вызываемых где угодно, например в языках C и Objective C. Константы и ссылки на переменные, определенные внутри функций, фиксируются и сохраняются в замыканиях. Функции рассматриваются как частные случаи замыканий и принимают следующие три формы:

Глобальные функции Вложенные функции Замыкающие выражения
Назови имя. Не фиксируйте никаких значений Назови имя. Захват значений из включающей функции Безымянные замыкания захватывают значения из соседних блоков

Замыкающие выражения в языке Swift 4 следуют четким, оптимизационным и упрощенным стилям синтаксиса, включая.

  • Вывод типов параметров и возвращаемых значений из контекста.
  • Неявный возврат из замыканий с одним выражением.
  • Сокращенные имена аргументов и
  • Синтаксис завершающего закрытия

Синтаксис

Ниже приводится общий синтаксис для определения закрытия, которое принимает параметры и возвращает тип данных.

{
   (parameters) −> return type in
   statements
}

Ниже приводится простой пример -

let studname = { print("Welcome to Swift Closures") }
studname()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Welcome to Swift Closures

Следующее закрытие принимает два параметра и возвращает значение типа Bool -

{     
   (Int, Int) −> Bool in
   Statement1
   Statement 2
   ---
   Statement n
}

Ниже приводится простой пример -

let divide = {
   (val1: Int, val2: Int) -> Int in 
   return val1 / val2 
}

let result = divide(200, 20)
print (result)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

10

Выражения в замыканиях

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

Программа возрастающего порядка

Сортировка строки достигается зарезервированной функцией Swift 4s "sorted", которая уже доступна в стандартной библиотеке. Функция сортирует заданные строки в порядке возрастания и возвращает элементы в новом массиве с тем же размером и типом данных, что и в старом массиве. Старый массив остается прежним.

Внутри отсортированной функции представлены два аргумента -

  • Значения типа Known представлены в виде массивов.

  • Содержимое массива (Int, Int) и возвращает логическое значение (Bool), если массив отсортирован правильно, он вернет истинное значение, иначе он вернет ложь.

Обычная функция с входной строкой записывается и передается сортированной функции для сортировки строк в новый массив, который показан ниже -

func ascend(s1: String, s2: String) -> Bool {
   return s1 > s2
}

let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)

Когда мы запускаем вышеуказанную программу с использованием игровой площадки, мы получаем следующий результат -

true

Первоначальный массив для сортировки мороженого задается как «Swift 4» и «отличный». Функция для сортировки массива объявляется как строковый тип данных, а ее возвращаемый тип упоминается как Boolean. Обе строки сравниваются и сортируются в порядке возрастания и сохраняются в новом массиве. Если сортировка выполнена успешно, функция вернет истинное значение, иначе вернет ложь.

Синтаксис выражения закрытия использует -

  • постоянные параметры,
  • переменные параметры и
  • inout параметры.

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

let sum = {
   (no1: Int, no2: Int) -> Int in 
   return no1 + no2 
}

let digits = sum(10, 20)
print(digits)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

30

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

Неявный возврат одного выражения

Здесь тип функции второго аргумента отсортированной функции дает понять, что значение типа Bool должно быть возвращено замыканием. Поскольку тело закрытия содержит одно выражение (s1> s2), которое возвращает значение типа Bool, двусмысленности нет, и ключевое слово return можно опустить.

Чтобы вернуть оператор Single expression в закрытии выражений, ключевое слово return опускается в его части объявления.

var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })

print(descending)
print(ascending)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

Сам оператор четко определяет, что когда строка1 больше, чем строка 2, возвращайте истину, в противном случае - ложь, поэтому оператор возврата здесь опускается.

Укупорочные средства известного типа

Рассмотрим сложение двух чисел. Мы знаем, что добавление вернет целочисленный тип данных. Следовательно, замыкания известных типов объявляются как -

let sub = {
   (no1: Int, no2: Int) -> Int in 
   return no1 - no2 
}

let digits = sub(10, 20)
print(digits)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

-10

Объявление сокращенных имен аргументов в качестве замыканий

Swift 4 автоматически предоставляет сокращенные имена аргументов для встроенных замыканий, которые можно использовать для обращения к значениям аргументов замыкания по именам $ 0, $1, $2 и так далее.

var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))

Здесь $ 0 и $ 1 относятся к первому и второму строковым аргументам замыкания.

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

200

Swift 4 помогает пользователю представлять встроенные замыкания в виде сокращенных имен аргументов, представляя $ 0, $1, $2 --- $ n.

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

Замыкания как операторские функции

Swift 4 предоставляет простой способ доступа к членам, просто предоставляя функции оператора как закрытие. В предыдущих примерах ключевое слово «Bool» используется для возврата либо «истина», если строки равны, в противном случае возвращается «ложь».

Выражение стало еще проще с помощью операторной функции в замыкании как -

let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
   (left: Int, right: Int) -> Bool in
   return left < right
})

let asc = numb.sorted(<)
print(asc)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[-30, -20, 18, 35, 42, 98]

Закрытие как трейлеры

Передача последнего аргумента функции в выражение замыкания объявляется с помощью 'Trailing Closures'. Он написан вне функции () с помощью {}. Его использование необходимо, когда невозможно написать встроенную функцию в одной строке.

reversed = sorted(names) { $0 > $1}

где {$ 0> $ 1} представлены как завершающие замыкания, объявленные за пределами (имена).

import Foundation
var letters = ["North", "East", "West", "South"]

let twoletters = letters.map({ 
   (state: String) -> String in
   return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})

let stletters = letters.map() { 
   $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString 
}
print(stletters)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[NO, EA, WE, SO]

Захват значений и ссылочных типов

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

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

Вложенная функция захватывает -

  • Аргументы внешней функции.
  • Захватите константы и переменные, определенные во внешней функции.

В Swift 4, когда константа или переменная объявляются внутри функции, ссылка на эти переменные также автоматически создается закрытием. Он также предоставляет возможность ссылаться на более чем две переменные как на одно и то же закрытие следующим образом:

let decrem = calcDecrement(forDecrement: 18)
decrem()

Вот oneDecrement и переменные Decrement будут указывать на один и тот же блок памяти как ссылку на замыкание.

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 100
   func decrementer() -> Int {
      overallDecrement -= total
      print(overallDecrement)
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

82
64
46

Каждый раз, когда вызывается внешняя функция calcDecrement, она вызывает функцию Decmenter (), уменьшает значение на 18 и возвращает результат с помощью внешней функции calcDecrement. Здесь calcDecrement действует как закрытие.

Несмотря на то, что функция декрементер () не имеет аргументов, закрытие по умолчанию обращается к переменным 'totalDecrement' и 'total' путем захвата их существующих значений. Копии значений для указанных переменных сохраняются с помощью новой функции Decmenter (). Swift 4 обрабатывает функции управления памятью, выделяя и освобождая пространства памяти, когда переменные не используются.

Перечисление - это определяемый пользователем тип данных, который состоит из набора связанных значений. Ключевое словоenum используется для определенного перечислимого типа данных.

Функции перечисления

Перечисление в Swift 4 также напоминает структуру C и Objective C.

  • Он объявлен в классе, и доступ к его значениям осуществляется через экземпляр этого класса.

  • Начальное значение члена определяется с помощью инициализаторов перечисления.

  • Его функциональность также расширена за счет обеспечения стандартной функциональности протокола.

Синтаксис

Перечисления вводятся ключевым словом enum и помещают их все определение в пару фигурных скобок:

enum enumname {
   // enumeration values are described here
}

Например, вы можете определить перечисление дней недели следующим образом:

enum DaysofaWeek {
   case Sunday
   case Monday
   ---
   case Saturday
}

пример

enum names {
   case Swift
   case Closures
}

var lang = names.Closures
lang = .Closures

switch lang {
   case .Swift:
      print("Welcome to Swift")
   case .Closures:
      print("Welcome to Closures")
   default:
      print("Introduction")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Welcome to Closures

Перечисление Swift 4 не назначает своим членам значения по умолчанию, такие как C и Objective C. Вместо этого члены явно определяются своими именами перечисления. Имя перечисления должно начинаться с заглавной буквы (например, enum DaysofaWeek).

var weekDay = DaysofaWeek.Sunday

Здесь имя перечисления "DaysofaWeek" присвоено переменной weekday.Sunday. Он сообщает компилятору, что тип данных, принадлежащий воскресенью, будет назначен последующим членам перечисления этого конкретного класса. Как только тип данных члена перечисления определен, члены могут быть доступны путем передачи значений и дальнейших вычислений.

Перечисление с оператором Switch

Оператор Swift 4 «Switch» также следует за многосторонним выбором. Только одна переменная доступна в определенное время в зависимости от указанного условия. Регистр по умолчанию в операторе switch используется для перехвата неуказанных случаев.

enum Climate {
   case India
   case America
   case Africa
   case Australia
}

var season = Climate.America
season = .America
switch season {
   case .India:
      print("Climate is Hot")
   case .America:
      print("Climate is Cold")
   case .Africa:
      print("Climate is Moderate")
   case .Australia:
      print("Climate is Rainy")
   
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Climate is Cold

Программа сначала определяет Climate как имя перечисления. Затем его члены, такие как «Индия», «Америка», «Африка» и «Австралия», объявляются принадлежащими к классу «Климат». Теперь член America назначен сезонной переменной. Кроме того, Switch case увидит значения, соответствующие .America, и перейдет к этому конкретному оператору. Результат будет отображаться как «Климат холодный». Точно так же все члены могут быть доступны через операторы switch. Если условие не выполняется, по умолчанию выводится сообщение «Климат непредсказуем».

Перечисление можно далее классифицировать по связанным значениям и необработанным значениям.

Разница между ассоциированными значениями и исходными значениями

Связанные ценности Необработанные значения
Различные типы данных Одинаковые типы данных
Пример: enum {10,0.8, "Hello"} Пример: enum {10,35,50}
Значения создаются на основе константы или переменной Предварительно заданные значения
Зависит от объявления каждый раз Значение для члена такое же

Перечисление со связанными значениями

enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}

var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Student Marks are: 98,97,95.

Рассмотрим, например, чтобы получить доступ к имени ученика и отметкам, защищенным в трех предметах, перечисление имя объявлено как студент, а члены, присутствующие в классе перечисления, - это имя, которое принадлежит строковому типу данных, отметки представлены как mark1, mark2 и mark3 типа данных Integer. Для доступа к имени ученика или набранным им оценкам

var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)

Теперь переключатель case напечатает имя студента, если этот блок case будет выполнен, иначе он напечатает отметки, полученные студентом. Если оба условия не выполняются, будет выполнен блок по умолчанию.

Перечисление с необработанными значениями

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

enum Month: Int {
   case January = 1, February, March, April, May, June, July, August,
      September, October, November, December
}

let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Value of the Month is: 5.

Swift 4 предоставляет гибкий строительный блок для использования конструкций как структур. Используя эти структуры, один раз можно определить методы и свойства конструкций.

В отличие от C и Objective C

  • Структура не требует файлов реализации и интерфейса.

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

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

Синтаксис

Structures are defined with a 'Struct' Keyword.
struct nameStruct {
   Definition 1
   Definition 2
   ---
   Definition N
}

Определение структуры

Рассмотрим, например, предположим, что нам нужно получить доступ к записи учеников, содержащей оценки по трем предметам, и узнать всего три предмета. Здесь markStruct используется для инициализации структуры с тремя метками как типа данных 'Int'.

struct MarkStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

Доступ к структуре и ее свойствам

Доступ к членам структуры осуществляется по имени ее структуры. Экземпляры структуры инициализируются ключевым словом let.

struct studentMarks {
   var mark1 = 100
   var mark2 = 200
   var mark3 = 300
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Mark1 is 100
Mark2 is 200
Mark3 is 300

Доступ к оценкам учащихся осуществляется по имени структуры «studentMarks». Члены структуры инициализируются как mark1, mark2, mark3 значениями целочисленного типа. Затем структура studentMarks () передается меткам с ключевым словом let. Здесь и далее «метки» будут содержать значения элементов структуры. Теперь значения печатаются путем доступа к значениям членов структуры с помощью '.' с его инициализированными именами.

struct MarksStruct {
   var mark: Int

   init(mark: Int) {
      self.mark = mark
   }
}

var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct     // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97

print(aStruct.mark)      // 98
print(bStruct.mark)      // 97

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

98
97

Лучшие практики использования структур

Язык Swift 4 предоставляет функциональные возможности для определения структур как пользовательских типов данных для построения функциональных блоков. Экземпляры структуры передаются по ее значению в определенные блоки для дальнейших манипуляций.

Потребность в структурах

  • Чтобы инкапсулировать простые значения данных.

  • Для копирования инкапсулированных данных и связанных с ними свойств по «значениям», а не по «ссылкам».

  • Структура для «копирования» и «ссылки».

Структуры в Swift 4 передают свои члены с их значениями, а не по ссылкам.

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int

   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

98
96
100

Другой пример

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
   
   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)

print(fail.mark1)
print(fail.mark2)
print(fail.mark3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

34
42
13

Сначала определяется структура markStruct с ее членами mark1, mark2 и mark3. Теперь переменные классов-членов инициализируются для хранения целочисленных значений. Затем создается копия членов структуры с ключевым словом self. После создания копии элементов структуры блок структуры с его метками параметров передается в переменную «метки», которая теперь будет содержать оценки учащихся. Затем метки печатаются как 98, 96, 100. На следующем этапе для тех же элементов структуры используется другой экземпляр с именем «fail», чтобы указать на те же элементы структуры разные метки. Затем результаты теперь печатаются как 34, 42, 13. Это ясно объясняет, что структуры будут иметь копию переменных-членов, а затем передадут элементы в свои следующие функциональные блоки.

Классы в Swift 4 - это строительные блоки гибких конструкций. Подобно константам, переменным и функциям пользователь может определять свойства и методы класса. Swift 4 предоставляет нам функциональность, благодаря которой при объявлении классов пользователям не нужно создавать интерфейсы или файлы реализации. Swift 4 позволяет нам создавать классы в виде одного файла, а внешние интерфейсы будут созданы по умолчанию после инициализации классов.

Преимущества занятий

  • Наследование приобретает свойства одного класса другому классу

  • Приведение типов позволяет пользователю проверять тип класса во время выполнения

  • Деинициализаторы заботятся об освобождении ресурсов памяти

  • Подсчет ссылок позволяет экземпляру класса иметь более одной ссылки

Общие характеристики классов и структур

  • Свойства определены для хранения значений
  • Индексы определены для предоставления доступа к значениям
  • Методы инициализируются для улучшения функциональности
  • Начальное состояние определяется инициализаторами
  • Функциональные возможности расширены за пределы значений по умолчанию
  • Подтверждение стандартов функциональности протокола

Синтаксис

Class classname {
   Definition 1
   Definition 2
   --- 
   Definition N
}

Определение класса

class student {
   var studname: String
   var mark: Int 
   var mark2: Int 
}

Синтаксис для создания экземпляров

let studrecord = student()

пример

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark = 300
}

let marks = studentMarks()
print("Mark is \(marks.mark)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Mark is 300

Доступ к свойствам класса как к ссылочным типам

Доступ к свойствам класса можно получить через '.' синтаксис. Название свойства разделяется знаком "." после имени экземпляра.

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark1 = 300
   var mark2 = 400
   var mark3 = 900
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Mark1 is 300
Mark2 is 400
Mark3 is 900

Операторы идентификации класса

Классы в Swift 4 ссылаются на несколько констант и переменных, указывающих на один экземпляр. Чтобы узнать о константах и ​​переменных, указывающих на конкретный экземпляр класса, используются операторы идентификации. Экземпляры классов всегда передаются по ссылке. В классах экземпляры NSString, NSArray и NSDictionary всегда назначаются и передаются как ссылка на существующий экземпляр, а не как копия.

Идентично операторам Не идентичны операторам
Используемый оператор (===) Используемый оператор (! ==)
Возвращает истину, если две константы или переменные указывают на один и тот же экземпляр. Возвращает истину, если две константы или переменные указывают на другой экземпляр.
class SampleClass: Equatable {
   let myProperty: String
   init(s: String) {
      myProperty = s
   }
}

func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
   return lhs.myProperty == rhs.myProperty
}

let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")

spClass1 === spClass2 // false
print("\(spClass1)")

spClass1 !== spClass2 // true
print("\(spClass2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

main.SampleClass
main.SampleClass

Язык Swift 4 предоставляет свойства для класса, перечисления или структуры для связывания значений. Свойства можно разделить на сохраненные свойства и вычисляемые свойства.

Разница между сохраненными свойствами и вычисленными свойствами

Сохраненная собственность Вычисленное свойство
Сохранять значения констант и переменных как экземпляр Вычисляйте значение, а не сохраняйте его
Предоставляется классами и структурами Предоставляется классами, перечислениями и структурами

И сохраненные, и вычисляемые свойства связаны с типом экземпляров. Когда свойства связаны со значениями его типа, он определяется как «Свойства типа». Сохраненные и вычисляемые свойства обычно связаны с экземплярами определенного типа. Однако свойства также могут быть связаны с самим типом. Такие свойства известны как свойства типа. Также используются наблюдатели за недвижимостью.

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

Сохраненные свойства

Swift 4 представляет концепцию хранимых свойств для хранения экземпляров констант и переменных. Сохраненные свойства констант определяются ключевым словом let, а сохраненные свойства переменных определяются ключевым словом var.

  • Во время определения свойство Stored предоставляет значение по умолчанию
  • Во время инициализации пользователь может инициализировать и изменять начальные значения.
struct Number {
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

67
3.1415

Рассмотрим следующую строку в приведенном выше коде -

let pi = 3.1415

Здесь переменная pi инициализируется как сохраненное значение свойства с экземпляром pi = 3,1415. Таким образом, при каждой ссылке на экземпляр он будет содержать только значение 3,1415.

Другой способ сохранить свойство - иметь постоянные структуры. Таким образом, весь экземпляр структур будет рассматриваться как «Сохраненные свойства констант».

struct Number {
   var digits: Int
   let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7

Вместо повторной инициализации «числа» на 8.7 он вернет сообщение об ошибке, указывающее, что «число» объявлено как постоянное.

Ленивая сохраненная собственность

Swift 4 предоставляет гибкое свойство под названием «Lazy Stored Property», где оно не будет вычислять начальные значения при первой инициализации переменной. Модификатор lazy используется перед объявлением переменной, чтобы сделать ее ленивым сохраненным свойством.

Ленивые свойства используются -

  • Чтобы отложить создание объекта.
  • Когда свойство зависит от других частей класса, которые еще не известны
class sample {
   lazy var no = number()    // `var` declaration is required.
}

class number {
   var name = "Swift 4"
}

var firstsample = sample()
print(firstsample.no.name)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swift 4

Переменные экземпляра

В Objective C хранимые свойства также имеют переменные экземпляра для целей резервного копирования для хранения значений, объявленных в сохраненном свойстве.

Swift 4 объединяет обе эти концепции в одно объявление «хранимого свойства». Вместо наличия соответствующей переменной экземпляра и резервного значения «сохраненное свойство» содержит всю интегрированную информацию, определенную в одном месте о свойстве переменных по имени переменной, типу данных и функциям управления памятью.

Вычисленные свойства

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

class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0

   var middle: (Double, Double) {
      get {
         return (length / 2, breadth / 2)
      }
      
      set(axis){
         no1 = axis.0 - (length / 2)
         no2 = axis.1 - (breadth / 2)
      }
   }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

(150.0, 75.0)
-150.0
-65.0

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

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

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

class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}

var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swift 4 Properties
3.09

Вычисляемые свойства как наблюдатели за свойствами

В Swift 4 для наблюдения и ответа на значения свойств используются Property Observers. Каждый раз, когда устанавливаются значения свойств, вызываются наблюдатели свойств. За исключением ленивых сохраненных свойств, мы можем добавить наблюдателей за свойством к «унаследованному» свойству методом «переопределения».

Наблюдатели за свойствами могут быть определены либо

  • Перед сохранением значения - willset

  • После сохранения нового значения - didset

  • Когда свойство установлено в инициализаторе willset и didset наблюдатели не могут быть вызваны.

class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }
      
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Локальные и глобальные переменные

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

Локальные переменные Глобальные переменные
Переменные, которые определены в контексте функции, метода или замыкания. Переменные, которые определены вне функции, метода, замыкания или контекста типа.
Используется для хранения и получения значений. Используется для хранения и получения значений.
Сохраненные свойства используются для получения и установки значений. Сохраненные свойства используются для получения и установки значений.
Также используются вычисленные свойства. Также используются вычисленные свойства.

Свойства типа

Свойства определяются в разделе «Определение типа» с помощью фигурных скобок {}, а область действия переменных также определяется ранее. Для определения свойств типа для типов значений используется ключевое слово static, а для типов классов - ключевое слово class.

Синтаксис

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}

Запрос и установка свойств

Так же, как свойства экземпляра Свойства типа запрашиваются и устанавливаются с помощью '.' Синтаксис только для типа вместо указания на экземпляр.

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

97
87

В языке Swift 4 функции, связанные с определенными типами, называются методами. В Objective C классы используются для определения методов, тогда как язык Swift 4 обеспечивает пользователю гибкость в использовании методов для классов, структур и перечислений.

Методы экземпляра

В языке Swift 4 доступ к экземплярам классов, структур и перечислений осуществляется через методы экземпляра.

Методы экземпляра обеспечивают функциональность

  • Для доступа и изменения свойств экземпляра
  • функциональность, связанная с потребностями экземпляра

Метод экземпляра можно записать в фигурные скобки {}. Он имеет неявный доступ к методам и свойствам экземпляра типа. Когда вызывается конкретный экземпляр типа, он получает доступ к этому конкретному экземпляру.

Синтаксис

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

пример

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}
let pri = calculations(a: 600, b: 300)
pri.result()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Result is: 880
Result is: 850

Вычисления классов определяют два метода экземпляра -

  • init () определен для сложения двух чисел a и b и сохранения их в результате 'res'
  • tot () используется для вычитания res из передаваемого значения c

Наконец, для печати вызываются методы вычислений со значениями для a и b. Доступ к методам экземпляра осуществляется через '.' точечный синтаксис

Имена локальных и внешних параметров

Функции Swift 4 описывают как локальные, так и глобальные объявления своих переменных. Точно так же соглашения об именах Swift 4 Methods также напоминают соглашения об именах в Objective C. Но характеристики объявлений имен локальных и глобальных параметров различны для функций и методов. Первый параметр в Swift 4 обозначается именами предлогов как «с», «для» и «по» для облегчения доступа к соглашениям об именах.

Swift 4 обеспечивает гибкость методов, объявляя имя первого параметра как имена локальных параметров, а имена остальных параметров - как имена глобальных параметров. Здесь "no1" объявлено методами Swift 4 как имена локальных параметров. 'no2' используется для глобальных деклараций и доступно из программы.

class division {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 / no2
      print(count)
   }
}

let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

600
320
3666

Имя внешнего параметра с символом # и _

Несмотря на то, что методы Swift 4 предоставляют имена первых параметров для локальных объявлений, пользователь может изменить имена параметров с локальных на глобальные объявления. Это можно сделать, добавив к имени первого параметра префикс символа «#». Таким образом, к первому параметру можно будет получить доступ глобально во всех модулях.

Когда пользователю необходимо получить доступ к последующим именам параметров с внешним именем, имя метода переопределяется с помощью символа «_».

class multiplication {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 * no2
      print(count)
   }
}

let counter = multiplication()

counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

2400
500
45000

Свойство Self в методах

У методов есть неявное свойство, известное как «я» для всех его экземпляров определенного типа. Свойство «Self» используется для ссылки на текущие экземпляры для его определенных методов.

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
      print("Inside Self Block: \(res)")
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}

let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)

pri.result()
sum.result()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450

Изменение типов значений из методов экземпляра

В Swift 4 языковые структуры и перечисления относятся к типам значений, которые нельзя изменить с помощью методов экземпляра. Однако язык Swift 4 обеспечивает гибкость для изменения типов значений путем «изменения» поведения. Mutate внесет любые изменения в методы экземпляра и вернется к исходной форме после выполнения метода. Кроме того, с помощью свойства self создается новый экземпляр для его неявной функции, который заменит существующий метод после его выполнения.

struct area {
   var length = 1
   var breadth = 1
   
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      length *= res
      breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

9
15
270
450
81000
135000

Собственная собственность для метода мутации

Мутирующие методы в сочетании со свойством self назначают новый экземпляр определенному методу.

struct area {
   var length = 1
   var breadth = 1
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      self.length *= res
      self.breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат. -

39
65

Типовые методы

Когда вызывается конкретный экземпляр метода, он вызывается как метод экземпляра; и когда метод вызывает определенный тип метода, он называется «методами типа». Методы типов для 'классов' определяются ключевым словом 'func', а методы типов структур и перечислений определяются с помощью ключевого слова 'static' перед ключевым словом 'func'.

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

class Math {
   class func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

struct absno {
   static func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

let no = Math.abs(number: -35)
let num = absno.abs(number: -5)

print(no)
print(num)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат. -

35
5

Доступ к элементам элементов коллекции, последовательности и списка в классах, структурах и перечислениях осуществляется с помощью индексов. Эти индексы используются для хранения и извлечения значений с помощью индекса. Доступ к элементам массива осуществляется с помощью someArray [index], а к его последующим элементам-членам в экземпляре Dictionary можно получить доступ как someDicitonary [key].

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

Синтаксис объявления нижнего индекса и его использование

Подведем итоги вычисленным свойствам. Подстрочные индексы также имеют тот же синтаксис, что и вычисляемые свойства. При запросе экземпляров типа индексы записываются внутри квадратных скобок, за которыми следует имя экземпляра. Синтаксис нижнего индекса следует той же структуре синтаксиса, что и синтаксис «метода экземпляра» и «вычисляемого свойства». Ключевое слово 'subscript' используется для определения индексов, и пользователь может указать один или несколько параметров с их типами возврата. Подстрочные индексы могут иметь свойства для чтения-записи или только для чтения, а экземпляры сохраняются и извлекаются с помощью свойств getter и setter, как и у вычисленных свойств.

Синтаксис

subscript(index: Int) −> Int {
   get {
      // used for subscript value declarations
   }
   set(newValue) {
      // definitions are written here
   }
}

Пример1

struct subexample {
   let decrementer: Int
   subscript(index: Int) -> Int {
      return decrementer / index
   }
}
let division = subexample(decrementer: 100)

print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times

Пример2

class daysofaweek {
   private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
      "Thursday", "Friday", "saturday"]
   subscript(index: Int) -> String {
      get {
         return days[index]
      }
      set(newValue) {
         self.days[index] = newValue
      }
   }
}
var p = daysofaweek()

print(p[0])
print(p[1])
print(p[2])
print(p[3])

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Sunday
Monday
Tuesday
Wednesday

Параметры в нижнем индексе

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

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

struct Matrix {
   let rows: Int, columns: Int
   var print: [Double]
   init(rows: Int, columns: Int) {
      self.rows = rows
      self.columns = columns
      print = Array(count: rows * columns, repeatedValue: 0.0)
   }
   subscript(row: Int, column: Int) -> Double {
      get {
         return print[(row * columns) + column]
      }
      set {
         print[(row * columns) + column] = newValue
      }
   }
}
var mat = Matrix(rows: 3, columns: 3)

mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

print("\(mat[0,0])")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

1.0

Подстрочный индекс Swift 4 поддерживает от одного параметра до нескольких объявлений параметров для соответствующих типов данных. Программа объявляет структуру «Matrix» как матрицу-массив размером 2 * 2 для хранения типов данных «Double». Параметр Matrix вводится с типами данных Integer для объявления строк и столбцов.

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

var mat = Matrix(rows: 3, columns: 3)

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

mat[0,0] = 1.0  
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

Способность принимать больше форм определяется как наследование. Как правило, класс может наследовать методы, свойства и функции другого класса. Классы можно разделить на подклассы и суперклассы.

  • Sub Class - когда класс наследует свойства, методы и функции от другого класса, он называется подклассом

  • Super Class - Класс, содержащий свойства, методы и функции для наследования других классов от самого себя, называется суперклассом.

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

Базовый класс

Класс, который не наследует методы, свойства или функции от другого класса, называется «Базовым классом».

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!
   
   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76

print(stname)
print(mark1)
print(mark2)
print(mark3)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swift 4
98
89
76

Класс с именем класса StudDetails определяется здесь как базовый класс, который используется для хранения имени учащихся, а три предмета помечаются как mark1, mark2 и mark3. Ключевое слово let используется для инициализации значения базового класса, а значение базового класса отображается на игровой площадке с помощью функции print.

Подкласс

Акт создания нового класса на основе существующего класса определяется как «подкласс». Подкласс наследует свойства, методы и функции своего базового класса. Для определения подкласса перед именем базового класса используется ':'

class StudDetails {
   var mark1: Int;
   var mark2: Int;
   
   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}

class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}

let marksobtained = display()
marksobtained.print()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Mark1:93, Mark2:89

Класс StudDetails определяется как суперкласс, в котором объявляются оценки учащихся, а подкласс «display» используется для наследования оценок от своего суперкласса. Подкласс определяет оценки учащихся и вызывает метод print () для отображения оценок учащихся.

Отмена

Доступ к экземпляру суперкласса, методам типа, экземпляру, свойствам типа и подклассу индексов обеспечивает концепцию переопределения. Ключевое слово override используется для переопределения методов, объявленных в суперклассе.

Доступ к методам суперкласса, свойствам и индексам

Ключевое слово super используется в качестве префикса для доступа к методам, свойствам и индексам, объявленным в суперклассе.

Отмена Доступ к методам, свойствам и индексам
Методы super.somemethod ()
Свойства super.someProperty ()
Индексы супер [someIndex]

Переопределение методов

Унаследованные методы экземпляра и типа могут быть переопределены ключевым словом override для наших методов, определенных в нашем подклассе. Здесь print () переопределяется в подклассе для доступа к свойству типа, упомянутому в суперклассе print (). Также новый экземпляр суперкласса cricket () создается как cricinstance.

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}

class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.print()

let tennisinstance = tennis()
tennisinstance.print()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Переопределение собственности

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

Переопределение методов получения и установки свойств

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

Это можно сделать двумя способами -

  • Когда сеттер определен для переопределения свойства, пользователь также должен определить геттер.

  • Если мы не хотим изменять получатель наследуемого свойства, мы можем просто передать наследуемое значение с помощью синтаксиса super.someProperty суперклассу.

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius of rectangle for 25.0  is now overridden as 3

Отмена наблюдателей за собственностью

Когда необходимо добавить новое свойство для унаследованного свойства, в Swift 4 вводится концепция «переопределения свойства». Это уведомляет пользователя об изменении значения унаследованного свойства. Но переопределение не применимо для унаследованных постоянных сохраненных свойств и унаследованных вычисляемых свойств, доступных только для чтения.

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

Окончательное свойство для предотвращения переопределения

Когда пользователю не нужно, чтобы другие пользователи имели доступ к методам, свойствам или индексам суперкласса, Swift 4 вводит свойство final для предотвращения переопределения. После объявления свойства final индексы не позволят переопределить методы суперкласса, свойства и его индексы. Отсутствует положение о наличии «окончательной» собственности в «суперклассе». Когда объявлено свойство final, пользователь может создавать дополнительные подклассы.

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

Поскольку суперкласс объявлен как «final», а его типы данных также объявлены как «final», программа не позволит создавать подклассы дальше и будет выдавать ошибки.

Классы, структуры и перечисления, однажды объявленные в Swift 4, инициализируются для подготовки экземпляра класса. Начальное значение инициализируется для сохраненного свойства, а также для новых экземпляров значения инициализируются для продолжения. Ключевое слово для создания функции инициализации выполняется методом init (). Инициализатор Swift 4 отличается от Objective-C тем, что не возвращает никаких значений. Его функция - проверять инициализацию вновь созданных экземпляров перед их обработкой. Swift 4 также обеспечивает процесс «деинициализации» для выполнения операций управления памятью после освобождения экземпляров.

Роль инициализатора для сохраненных свойств

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

  • Для создания начального значения.

  • Чтобы присвоить значение свойства по умолчанию в определении свойства.

  • Для инициализации экземпляра для определенного типа данных используется init (). Внутри функции init () аргументы не передаются.

Синтаксис

init() {
   //New Instance initialization goes here
}

пример

struct rectangle {
   var length: Double
   var breadth: Double
   init() {
      length = 6
      breadth = 12
   }
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area of rectangle is 72.0

Здесь структура 'rectangle' инициализируется с элементами длины и ширины как типы данных 'Double'. Метод Init () используется для инициализации значений для вновь созданных членов length и double. Площадь прямоугольника вычисляется и возвращается путем вызова функции прямоугольника.

Установка значений свойств по умолчанию

Язык Swift 4 предоставляет функцию Init () для инициализации сохраненных значений свойств. Кроме того, у пользователя есть возможность инициализировать значения свойств по умолчанию при объявлении членов класса или структуры. Когда свойство принимает одно и то же значение на протяжении всей программы, мы можем объявить его только в разделе объявления, а не инициализировать его в init (). Установка значений свойств по умолчанию позволяет пользователю, когда для классов или структур определено наследование.

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area of rectangle is 72

Здесь вместо объявления длины и ширины в init () значения инициализируются в самом объявлении.

Инициализация параметров

В языке Swift 4 пользователь может инициализировать параметры как часть определения инициализатора с помощью init ().

struct Rectangle {
   var length: Double
   var breadth: Double
   var area: Double
   
   init(fromLength length: Double, fromBreadth breadth: Double) {
      self.length = length
      self.breadth = breadth
      area = length * breadth
   }
   init(fromLeng leng: Double, fromBread bread: Double) {
      self.length = leng
      self.breadth = bread
      area = leng * bread
   }
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area is: 72.0
area is: 432.0

Локальные и внешние параметры

Параметры инициализации имеют как локальные, так и глобальные имена параметров, аналогичные именам параметров функции и метода. Объявление локального параметра используется для доступа в теле инициализации, а объявление внешнего параметра используется для вызова инициализатора. Инициализаторы Swift 4 отличаются от инициализатора функций и методов тем, что они не определяют, какой инициализатор используется для вызова каких функций.

Чтобы преодолеть это, Swift 4 вводит автоматическое внешнее имя для каждого параметра в init (). Это автоматическое внешнее имя эквивалентно локальному имени, записанному перед каждым параметром инициализации.

struct Days {
   let sunday, monday, tuesday: Int
   init(sunday: Int, monday: Int, tuesday: Int) {
      self.sunday = sunday
      self.monday = monday
      self.tuesday = tuesday
   }
   init(daysofaweek: Int) {
      sunday = daysofaweek
      monday = daysofaweek
      tuesday = daysofaweek
   }
}

let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")

let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4

Параметры без внешних имен

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

struct Rectangle {
   var length: Double
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area is: 180.0
area is: 370.0
area is: 110.0

Дополнительные типы свойств

Когда сохраненное свойство в некотором экземпляре не возвращает никакого значения, это свойство объявляется с «необязательным» типом, указывающим, что для этого конкретного типа не возвращается «никакого значения». Когда сохраненное свойство объявлено как «необязательное», оно автоматически инициализирует значение «nil» во время самой инициализации.

struct Rectangle {
   var length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Изменение постоянных свойств во время инициализации

Инициализация также позволяет пользователю изменять значение постоянного свойства. Во время инициализации свойство класса позволяет изменять его экземпляры класса суперклассом, а не подклассом. Рассмотрим, например, что в предыдущей программе «длина» объявлена ​​как «переменная» в основном классе. Приведенная ниже программная переменная 'length' изменена как 'постоянная' переменная.

struct Rectangle {
   let length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Инициализаторы по умолчанию

Инициализаторы по умолчанию предоставляют новый экземпляр для всех объявленных свойств базового класса или структуры со значениями по умолчанию.

class defaultexample {
   var studname: String?
   var stmark = 98
   var pass = true
}
var result = defaultexample()

print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат. -

result is: nil
result is: 98
result is: true

Вышеупомянутая программа определена с именем класса как defaultexample. Три функции-члена инициализируются по умолчанию как «имя группы?» для хранения значений 'nil', 'stmark' как 98 и 'pass' как логическое значение 'true'. Аналогичным образом значения членов в классе могут быть инициализированы по умолчанию перед обработкой типов членов класса.

Поэлементные инициализаторы для типов структур

Когда пользовательские инициализаторы не предоставляются пользователем, типы структур в Swift 4 автоматически получают «поэлементный инициализатор». Его основная функция - инициализировать новые экземпляры структуры с помощью поэлементной инициализации по умолчанию, а затем новые свойства экземпляра передаются поэлементной инициализации по имени.

struct Rectangle {
   var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Area of rectangle is: 24.0
Area of rectangle is: 32.0

Структуры инициализируются по умолчанию для своих функций принадлежности во время инициализации для "длины" как "100.0" и "ширины" как "200.0". Но значения переопределяются при обработке переменных длины и ширины как 24.0 и 32.0.

Делегирование инициализатора для типов значений

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

struct Stmark {
   var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
   var m1 = 0.0, m2 = 0.0
}

struct block {
   var average = stdb()
   var result = Stmark()
   init() {}
   init(average: stdb, result: Stmark) {
      self.average = average
      self.result = result
   }

   init(avg: stdb, result: Stmark) {
      let tot = avg.m1 - (result.mark1 / 2)
      let tot1 = avg.m2 - (result.mark2 / 2)
      self.init(average: stdb(m1: tot, m2: tot1), result: result)
   }
}

let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")

let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")

let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

Правила делегирования инициализатора

Типы значений Типы классов
Наследование не поддерживается для типов значений, таких как структуры и перечисления. Обращение к другим инициализаторам осуществляется через self.init Наследование поддерживается. Проверяет, что все сохраненные значения свойств инициализированы

Наследование и инициализация классов

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

Назначенные инициализаторы и удобные инициализаторы

Назначенный инициализатор Инициализатор удобства
Считается первичной инициализацией класса Считается поддержкой инициализации для класса
Все свойства класса инициализируются, и для дальнейшей инициализации вызывается соответствующий инициализатор суперкласса. Назначенный инициализатор вызывается с удобным инициализатором для создания экземпляра класса для конкретного варианта использования или типа входного значения.
По крайней мере, один назначенный инициализатор определен для каждого класса Нет необходимости в обязательном определении удобных инициализаторов, если класс не требует инициализаторов.
Init (параметры) {операторы} удобство init (параметры) {операторы}

Программа для назначенных инициализаторов

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int // new subclass storage
   init(no1 : Int, no2 : Int) {
      self.no2 = no2 // initialization
      super.init(no1:no1) // redirect to superclass
   }
}

let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

res is: 10
res is: 10
res is: 20

Программа для удобных инициализаторов

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int
   init(no1 : Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

res is: 20
res is: 30
res is: 50

Наследование и переопределение инициализатора

Swift 4 не позволяет своим подклассам наследовать инициализаторы суперкласса для своих типов членов по умолчанию. Наследование применимо к инициализаторам суперкласса только в некоторой степени, что будет обсуждаться в разделе «Автоматическое наследование инициализатора».

Когда пользователю необходимо определить инициализаторы в суперклассе, подкласс с инициализаторами должен быть определен пользователем как пользовательская реализация. Если необходимо выполнить переопределение подклассом, необходимо объявить ключевое слово «override» суперкласса.

class sides {
   var corners = 4
   var description: String {
      return "\(corners) sides"
   }
}

let rectangle = sides()
print("Rectangle: \(rectangle.description)")

class pentagon: sides {
   override init() {
      super.init()
      corners = 5
   }
}

let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Rectangle: 4 sides
Pentagon: 5 sides

Назначенные и удобные инициализаторы в действии

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}

let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")

class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Planet name is: Mercury
No Planets like that: [No Planets]

Неудачный инициализатор

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

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

Чтобы перехватить исключения, вызванные методом инициализации, Swift 4 создает гибкую инициализацию, называемую «сбойный инициализатор», чтобы уведомить пользователя о том, что что-то осталось незамеченным при инициализации элементов структуры, класса или перечисления. Ключевое слово для обнаружения сбойного инициализатора - «init?». Кроме того, отказоустойчивые и исправные инициализаторы не могут быть определены с одинаковыми типами параметров и именами.

struct studrecord {
   let stname: String
   init?(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Student name is specified
Student name is left blank

Неудачные инициализаторы для перечислений

Язык Swift 4 обеспечивает гибкость использования инициализаторов Failable для перечислений, чтобы уведомлять пользователя, когда члены перечисления не инициализируют значения.

enum functions {
   case a, b, c, d
   init?(funct: String) {
      switch funct {
      case "one":
         self = .a
      case "two":
         self = .b
      case "three":
         self = .c
      case "four":
         self = .d
      default:
         return nil
      }
   }
}
let result = functions(funct: "two")

if result != nil {
   print("With In Block Two")
}
let badresult = functions(funct: "five")

if badresult == nil {
   print("Block Does Not Exist")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

With In Block Two
Block Does Not Exist

Неудачные инициализаторы для классов

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

class studrecord {
   let studname: String!
   init?(studname: String) {
      self.studname = studname
      if studname.isEmpty { return nil }
   }
}

if let stname = studrecord(studname: "Failable Initializers") {
   print("Module is \(stname.studname)")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Module is Optional("Failable Initializers")

Отмена неудачного инициализатора

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

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

Неисправный инициализатор никогда не может делегировать отказавшему инициализатору.

В приведенной ниже программе описаны отказоустойчивые и исправные инициализаторы.

class Planet {
   var name: String
   
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")
   
class planets: Planet {
   var count: Int
   
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Planet name is: Mercury
No Planets like that: [No Planets]

Файл init! Неудачный инициализатор

Swift 4 предоставляет init? для определения необязательного сбойного инициализатора экземпляра. Для определения неявно развернутого необязательного экземпляра определенного типа 'init!' указан.

struct studrecord {
let stname: String

   init!(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}

let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Student name is specified
Student name is left blank

Необходимые инициализаторы

Чтобы объявить каждый подкласс ключевого слова initialize 'required', необходимо определить перед функцией init ().

class classA {
   required init() {
      var a = 10
      print(a)
   }
}

class classB: classA {
   required init() {
      var b = 30
      print(b)
   }
}

let res = classA()
let print = classB()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

10
30
10

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

Деинициализация для освобождения места в памяти

Swift 4 автоматически освобождает ваши экземпляры, когда они больше не нужны, чтобы освободить ресурсы. Swift 4 управляет памятью экземпляров с помощью автоматического подсчета ссылок (ARC), как описано в разделе Автоматический подсчет ссылок. Обычно вам не нужно выполнять ручную очистку, когда ваши экземпляры освобождены. Однако, когда вы работаете со своими собственными ресурсами, вам может потребоваться выполнить дополнительную очистку самостоятельно. Например, если вы создаете настраиваемый класс для открытия файла и записи в него некоторых данных, вам может потребоваться закрыть файл до того, как экземпляр класса будет освобожден.

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()

print(counter)
print = nil
print(counter)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

1
0

Когда оператор print = nil опущен, значения счетчика остаются прежними, поскольку он не деинициализируется.

var counter = 0; // for reference counting

class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

1
1

Функции управления памятью и ее использование обрабатываются на языке Swift 4 посредством автоматического подсчета ссылок (ARC). ARC используется для инициализации и деинициализации системных ресурсов, тем самым освобождая пространства памяти, используемые экземплярами класса, когда экземпляры больше не нужны. ARC отслеживает информацию об отношениях между нашими экземплярами кода для эффективного управления ресурсами памяти.

Функции ARC

  • ARC выделяет часть памяти для хранения информации каждый раз, когда новый экземпляр класса создается с помощью init ().

  • Информация о типе экземпляра и его значениях хранится в памяти.

  • Когда экземпляр класса больше не нужен, он автоматически освобождает пространство памяти с помощью deinit () для дальнейшего хранения и извлечения экземпляра класса.

  • ARC отслеживает свойства, константы и переменные экземпляров класса, на которые в настоящее время ссылаются, так что deinit () применяется только к этим неиспользуемым экземплярам.

  • ARC поддерживает «сильную ссылку» на эти свойства экземпляра класса, константы и переменные, чтобы ограничить освобождение, когда экземпляр класса в настоящее время используется.

Программа ARC

class StudDetails {
   var stname: String!
   var mark: Int!
   
   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Swift 4
98

Экземпляры классов ARC Strong Reference Cycles

class studmarks {
   let name: String
   var stud: student?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Initializing: Swift 4
Initializing: ARC

Слабые и бесхозные ссылки ARC

Свойства типа класса имеют два способа разрешить циклы сильных ссылок:

  • Слабые ссылки
  • Необоснованные ссылки

Эти ссылки используются для того, чтобы один экземпляр мог ссылаться на другие экземпляры в цикле ссылок. Тогда экземпляры могут ссылаться на каждый экземпляр вместо того, чтобы заботиться о цикле сильных ссылок. Когда пользователь знает, что какой-то экземпляр может возвращать нулевые значения, мы можем указать это, используя слабую ссылку. Когда экземпляр собирается вернуть что-то, а не nil, объявите это с помощью ссылки без владельца.

Слабая справочная программа

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

ARC Is The Main Module
Sub Module with its topic number is 4

Независимая справочная программа

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student
   
   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

ARC
Marks Obtained by the student is 98

Циклы сильных ссылок для замыканий

Когда мы назначаем замыкание свойству экземпляра класса и телу замыкания для захвата конкретного экземпляра, может возникнуть цикл сильных ссылок. Сильная ссылка на закрытие определяется «self.someProperty» или «self.someMethod ()». Циклы сильных ссылок используются в качестве типов ссылок для замыканий.

class HTMLElement {
   let samplename: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

<p>Welcome to Closure SRC</p>

Слабые и бесхозные ссылки

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

class HTMLElement {
   let module: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

<Inside>ARC Weak References</Inside>
Inside the deinit()

Процесс запроса, вызова свойств, индексов и методов для необязательного элемента, который может иметь значение «nil», определяется как необязательное связывание. Необязательная цепочка возвращает два значения -

  • если необязательный параметр содержит 'значение', тогда вызов его связанного свойства, методов и индексов возвращает значения

  • если необязательный параметр содержит значение 'nil', все его связанные свойства, методы и индексы возвращают nil

Поскольку несколько запросов к методам, свойствам и индексам сгруппированы вместе, отказ одной цепочки повлияет на всю цепочку и приведет к значению «ноль».

Дополнительное связывание как альтернатива принудительному разворачиванию

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

Необязательная цепочка '?' Доступ к методам, свойствам и индексам. Дополнительная цепочка '!' заставить распаковывать
? помещается после необязательного значения для вызова свойства, метода или индекса ! помещается после необязательного значения для вызова свойства, метода или индекса, чтобы принудительно развернуть значение
Изящно терпит неудачу, если необязательный параметр равен 'nil' Принудительное развертывание вызывает ошибку времени выполнения, если необязательный параметр равен 'nil'

Программа для необязательного связывания с '!'

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string

Вышеупомянутая программа объявляет «избирательный опрос» как имя класса и содержит «кандидат» как функцию принадлежности. Подкласс объявлен как 'poll booth' и 'name' как его функция принадлежности, которая инициализируется как 'MP'. Вызов суперкласса инициализируется путем создания экземпляра «cand» с необязательным «!». Поскольку значения не объявлены в его базовом классе, сохраняется значение 'nil', тем самым возвращая фатальную ошибку процедурой принудительного развертывания.

Программа для необязательного связывания с '?'

class ElectionPoll {
   var candidate: Pollbooth?
}

class Pollbooth {
   var name = "MP"
}
let cand = ElectionPoll()

if let candname = cand.candidate?.name {
   print("Candidate name is \(candname)")
} else {
   print("Candidate name cannot be retreived")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Candidate name cannot be retreived

Программа выше объявляет «избирательный опрос» как имя класса и содержит «кандидат» как функцию принадлежности. Подкласс объявлен как 'poll booth' и 'name' как его функция принадлежности, которая инициализируется как 'MP'. Вызов суперкласса инициализируется путем создания экземпляра "cand" с необязательным "?". Поскольку значения не объявлены в его базовом классе, значение 'nil' сохраняется и печатается в консоли блоком обработчика else.

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

Язык Swift 4 также предоставляет концепцию необязательной цепочки для объявления более одного подкласса как классов модели. Эта концепция будет очень полезна для определения сложных моделей и для доступа к вспомогательным свойствам свойств, методов и индексов.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var street: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
   print("Area of rectangle is \(rectarea)")
} else {
   print("Rectangle Area is not specified")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Rectangle Area is not specified

Вызов методов через необязательную цепочку

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }

   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Area of circle is not specified

Функция circleprint (), объявленная внутри подкласса circle (), вызывается путем создания экземпляра с именем circname. Функция вернет значение, если оно содержит какое-либо значение, в противном случае она вернет определенное пользователем сообщение печати, проверив оператор 'if circname.print? .Circleprint ()! = Nil'.

Доступ к индексам через опциональную цепочку

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

Программа 1

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname =  radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius is not specified.

В приведенной выше программе значения экземпляра для функции принадлежности "radiusName" не указаны. Следовательно, программный вызов функции вернет только остальную часть, тогда как для возврата значений мы должны определить значения для конкретной функции принадлежности.

Программа 2

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius is measured in Units.

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

Доступ к индексам необязательного типа

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }

   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")

let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--

print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])

print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

К необязательным значениям индексов можно получить доступ, указав их значения индексов. Доступ к нему можно получить как нижний индекс [0], нижний индекс [1] и т. Д. Значения нижнего индекса по умолчанию для «радиуса» сначала назначаются как [35, 45, 78, 101] и для «Круг» [90, 45, 56]] . Затем значения нижнего индекса изменяются с Радиуса [0] на 78 и Круг [1] на 45.

Связывание нескольких уровней цепочки

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

Можно связать несколько опциональных цепочек -

Если тип получения не является необязательным, необязательная цепочка вернет необязательное значение. Например, если String через необязательную цепочку вернет String? Значение

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius is not specified.

В приведенной выше программе значения экземпляра для функции принадлежности "radiusName" не указаны. Следовательно, программный вызов функции вернет только другую часть, тогда как для возврата значений мы должны определить значения для конкретной функции принадлежности.

Если тип получения уже является необязательным, то необязательное связывание также вернет необязательное значение. Например, если String? Доступен через необязательную цепочку, он вернет String? Значение..

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Radius is measured in Units.

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

Цепочка методов с дополнительными возвращаемыми значениями

Необязательная цепочка также используется для доступа к определенным методам подклассов.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Area of circle is not specified

Чтобы проверить тип экземпляра, в языке Swift 4 в игру вступает «Типовое приведение». Он используется для проверки того, принадлежит ли тип экземпляра определенному суперклассу или подклассу или он определен в своей собственной иерархии.

Приведение типов Swift 4 предоставляет два оператора is для проверки типа значения и as, а также для приведения значения типа к другому типу. Приведение типов также проверяет, соответствует ли тип экземпляра определенному стандарту соответствия протоколу.

Определение иерархии классов

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

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz

Проверка типа

Проверка типа выполняется с помощью оператора «is». Оператор проверки типа «is» проверяет, принадлежит ли экземпляр к определенному типу подкласса, и возвращает «истину», если он принадлежит этому экземпляру, иначе он вернет «ложь».

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0
for item in sa {
   if item is Chemistry {
      ++chemCount
   } else if item is Maths {
      ++mathsCount
   }
}

print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics

Понижение

Понижение типа подкласса можно выполнить с помощью двух операторов (as? И as!). 'As?' возвращает необязательное значение, когда значение возвращает ноль. Он используется для проверки успешного понижающего преобразования.

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

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series

Приведение типов: любой и любой объект

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

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()

exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:   
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

AnyObject

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

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in saprint {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

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

Swift Extension Functionalities -

  • Добавление вычисляемых свойств и свойств вычисляемого типа
  • Определение методов экземпляра и типа.
  • Предоставление новых инициализаторов.
  • Определение индексов
  • Определение и использование новых вложенных типов
  • Приведение существующего типа в соответствие с протоколом

Расширения объявляются с ключевым словом extension

Синтаксис

extension SomeType {
   // new functionality can be added here
}

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

extension SomeType: SomeProtocol, AnotherProtocol {
   // protocol requirements is described here
}

Вычисленные свойства

Вычисленные свойства «экземпляр» и «тип» также могут быть расширены с помощью расширений.

extension Int {
   var add: Int {return self + 100 }
   var sub: Int { return self - 10 }
   var mul: Int { return self * 10 }
   var div: Int { return self / 5 }
}

let addition = 3.add
print("Addition is \(addition)")

let subtraction = 120.sub
print("Subtraction is \(subtraction)")

let multiplication = 39.mul
print("Multiplication is \(multiplication)")

let division = 55.div
print("Division is \(division)")

let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154

Инициализаторы

Swift 4 обеспечивает гибкость для добавления новых инициализаторов к существующему типу с помощью расширений. Пользователь может добавлять свои собственные настраиваемые типы для расширения уже определенных типов, а также возможны дополнительные параметры инициализации. Расширения поддерживают только init (). deinit () не поддерживается расширениями.

struct sum {
   var num1 = 100, num2 = 200
}

struct diff {
   var no1 = 200, no2 = 100
}

struct mult {
   var a = sum()
   var b = diff()
}

let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")

let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")

extension mult {
   init(x: sum, y: diff) {
      let X = x.num1 + x.num2
      let Y = y.no1 + y.no2
   }
}

let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")

let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)

Методы

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

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation()
      }
   }
}

4.topics(summation: {
   print("Inside Extensions Block")
})

3.topics(summation: {
   print("Inside Type Casting Block")
})

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block

Функция themes () принимает аргумент типа '(суммирование: () → ())', чтобы указать, что функция не принимает никаких аргументов и не возвращает никаких значений. Чтобы вызвать эту функцию несколько раз, инициализируется блок for и инициализируется вызов метода с topic ().

Методы мутирования экземпляров

Методы экземпляра также можно изменять, если они объявлены как расширения.

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

extension Double {
   mutating func square() {
      let pi = 3.1415
      self = pi * self * self
   }
}

var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")

var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")

var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735

Индексы

Добавление новых индексов к уже объявленным экземплярам также возможно с помощью расширений.

extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self / no1) % 10
   }
}

print(12[0])
print(7869[1])
print(786543[2])

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

2
6
5

Вложенные типы

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

extension Int {
   enum calc {
      case add
      case sub
      case mult
      case div
      case anything
   }
   var print: calc {
      switch self {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
      }
   }
}

func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
         case .sub:
            print(" 20 ")
         case .mult:
            print(" 30 ")
         case .div:
            print(" 40 ")
         default:
            print(" 50 ")
      }
   }
}
result(numb: [0, 1, 2, 3, 4, 7])

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

10
20
30
40
50
50

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

Синтаксис

Протоколы также следуют синтаксису, аналогичному синтаксису классов, структур и перечислений -

protocol SomeProtocol {
   // protocol definition 
}

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

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

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

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

Требования к свойствам и методам

Протокол используется для указания свойства типа определенного класса или свойства экземпляра. Он просто указывает только тип или свойство экземпляра, а не указывает, является ли это свойство хранимым или вычисляемым. Кроме того, он используется, чтобы указать, является ли свойство «gettable» или «settable».

Требования к свойствам объявляются ключевым словом var как переменные свойства. {get set} используется для объявления свойств gettable и settable после объявления их типа. Gettable упоминается свойством {get} после объявления их типа.

protocol classa {
   var marks: Int { get set }
   var result: Bool { get }
   
   func attendance() -> String
   func markssecured() -> String
}

protocol classb: classa {
   var present: Bool { get set }
   var subject: String { get set }
   var stname: String { get set }
}

class classc: classb {
   var marks = 96
   let result = true
   var present = false
   var subject = "Swift 4 Protocols"
   var stname = "Protocols"

   func attendance() -> String {
      return "The \(stname) has secured 99% attendance"
   }
   func markssecured() -> String {
      return "\(stname) has scored \(marks)"
   }
}

let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

98
true
false
Swift 4 Protocols
Swift 4

Требования к методу мутации

protocol daysofaweek {
   mutating func print()
}

enum days: daysofaweek {
   case sun, mon, tue, wed, thurs, fri, sat 
   mutating func print() {
      switch self {
         case sun:
            self = sun
            print("Sunday")
         case mon:
            self = mon
            print("Monday")
         case tue:
            self = tue
            print("Tuesday")
         case wed:
            self = wed
            print("Wednesday")
         case mon:
            self = thurs
            print("Thursday")
         case tue:
            self = fri
            print("Friday")
         case sat:
            self = sat
            print("Saturday")
         default:
            print("NO Such Day")
      }
   }
}

var res = days.wed
res.print()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Wednesday

Требования к инициализатору

Swing позволяет пользователю инициализировать протоколы в соответствии с типом соответствия, аналогичным нормальным инициализаторам.

Синтаксис

protocol SomeProtocol {
   init(someParameter: Int)
}

Например

protocol tcpprotocol {
   init(aprot: Int)
}

Реализации классов требований инициализатора протокола

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

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

Соответствие протоколу гарантируется для всех подклассов для явной или унаследованной реализации с помощью модификатора required.

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

protocol tcpprotocol {
   init(no1: Int)
}

class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}

class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

res is: 20
res is: 30
res is: 50

Протоколы как типы

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

Протоколы могут быть доступны как типы в -

  • Функция, метод или инициализация как параметр или возвращаемый тип

  • Константа, переменная или свойство

  • Массивы, словари или другие контейнеры как элементы

protocol Generator {
   typealias members
   func next() -> members?
}

var items = [10,20,30].generate()
while let x = items.next() {
   print(x)
}

for lists in map([1,2,3], {i in i*5}) {
   print(lists)
}

print([100,200,300])
print(map([1,2,3], {i in i*10}))

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

Добавление соответствия протоколу с расширением

Существующий тип может быть адаптирован и согласован с новым протоколом с использованием расширений. Новые свойства, методы и индексы могут быть добавлены к существующим типам с помощью расширений.

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}
class Person {
   let firstname: String
   let lastname: String
   var age: Int
   
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   func agetype() -> String {
      switch age {
         case 0...2:
            return "Baby"
         case 2...12:
            return "Child"
         case 13...19:
            return "Teenager"
         case let x where x > 65:
            return "Elderly"
         default:
            return "Normal"
      }
   }
}

Наследование протокола

Swift 4 позволяет протоколам наследовать свойства от определенных свойств. Это похоже на наследование классов, но с возможностью перечисления нескольких унаследованных протоколов, разделенных запятыми.

protocol classa {
   var no1: Int { get set }
   func calc(sum: Int)
}
protocol result {
   func print(target: classa)
}
class student2: result {
   func print(target: classa) {
      target.calc(sum: 1)
   }
}
class classb: result {
   func print(target: classa) {
      target.calc(sum: 5)
   }
}

class student: classa {
   var no1: Int = 10
   
   func calc(sum: Int) {
      no1 -= sum
      print("Student attempted \(sum) times to pass")
         
      if no1 <= 0 {
         print("Student is absent for exam")
      }
   }
}

class Player {
   var stmark: result!

   init(stmark: result) {
      self.stmark = stmark
   }
   func print(target: classa) {
      stmark.print(target: target)
   }
}

var marks = Player(stmark: student2())
var marksec = student()

marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam

Протоколы только класса

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

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

res is: 20
res is: 30
res is: 50

Состав протокола

Swift 4 позволяет одновременно вызывать несколько протоколов с помощью композиции протоколов.

Синтаксис

protocol<SomeProtocol, AnotherProtocol>

пример

protocol stname {
   var name: String { get }
}
protocol stage {
   var age: Int { get }
}
struct Person: stname, stage {
   var name: String
   var age: Int
}
func print(celebrator: stname & stage) {
   print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

Проверка на соответствие протоколу

Соответствие протоколу проверяется операторами is и as аналогично приведению типов.

  • Оператор is возвращает true, если экземпляр соответствует стандарту протокола, и false, если он терпит неудачу.

  • В as? версия оператора downcast возвращает необязательное значение типа протокола, и это значение равно нулю, если экземпляр не соответствует этому протоколу.

  • Версия as оператора понижающего преобразования принудительно приводит к понижающему типу протокола и вызывает ошибку времени выполнения, если понижающее преобразование не удается.

import Foundation

@objc protocol rectangle {
   var area: Double { get }
}
@objc class Circle: rectangle {
   let pi = 3.1415927
   var radius: Double
   var area: Double { return pi * radius * radius }
   init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
   var area: Double
   init(area: Double) { self.area = area }
}
class sides {
   var rectsides: Int
   init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]

for object in objects {
   if let objectWithArea = object as? rectangle {
      print("Area is \(objectWithArea.area)")
   } else {
      print("Rectangle area is not defined")
   }
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Area is 12.5663708
Area is 198.0
Rectangle area is not defined

Язык Swift 4 предоставляет «общие» функции для написания гибких и многоразовых функций и типов. Обобщения используются, чтобы избежать дублирования и обеспечить абстракцию. Стандартные библиотеки Swift 4 построены с использованием универсального кода. Типы Swift 4s «Массивы» и «Словарь» относятся к общим коллекциям. С помощью массивов и словарей массивы определяются для хранения значений «Int» и «String» или любых других типов.

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}

var numb1 = 100
var numb2 = 200

print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

Общие функции: параметры типа

Универсальные функции могут использоваться для доступа к любому типу данных, например Int или String.

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

Функция exchange () используется для обмена значениями, как описано в приведенной выше программе, а <T> используется как параметр типа. В первый раз вызывается функция exchange () для возврата значений типа Int, а второй вызов функции exchange () возвращает значения типа String. В угловые скобки можно указывать несколько типов параметров, разделенных запятыми.

Параметры типа называются так, как определено пользователем, чтобы знать назначение параметра типа, который он содержит. Swift 4 предоставляет <T> как имя параметра универсального типа. Однако параметры типа, такие как массивы и словари, также могут быть названы ключом, значением, чтобы идентифицировать их принадлежность к типу Dictionary.

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

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

let deletetos = tos.pop()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

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

Расширение свойства стека для определения вершины элемента включается с помощью ключевого слова extension.

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

Ограничения типа

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

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

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

Swift 4 позволяет объявлять связанные типы внутри определения протокола с помощью ключевого слова connectedtype.

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<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: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Где пункты

Ограничения типа позволяют пользователю определять требования к параметрам типа, связанным с универсальной функцией или типом. Для определения требований для связанных типов предложения where объявляются как часть списка параметров типа. Ключевое слово 'where' помещается сразу после списка параметров типа, за которым следуют ограничения связанных типов, отношения равенства между типами и связанные типы.

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
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: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
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
}  
var tos = Stack<String>()

tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

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

Модель контроля доступа основана на модулях и исходных файлах.

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

Язык Swift 4 предоставляет три различных уровня доступа. Это открытый, внутренний и частный доступ.

S.No Уровни доступа и определение
1

Public

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

2

Internal

Позволяет использовать сущности в любом исходном файле из их определяющего модуля, но не в любом исходном файле за пределами этого модуля.

3

Private

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

Синтаксис

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Контроль доступа для типов функций

Некоторые функции могут иметь аргументы, объявленные внутри функции, без каких-либо возвращаемых значений. Следующая программа объявляет a и b в качестве аргументов функции sum (). Внутри самой функции значения аргументов a и b передаются путем вызова функции sum (), и ее значения печатаются, тем самым устраняя возвращаемые значения. Чтобы сделать возвращаемый тип функции закрытым, объявите общий уровень доступа к функции с помощью модификатора private.

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

30 20
50 40
30 24

Контроль доступа для типов перечисления

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
   
}

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Student Marks are: 98,97,95

Перечисления на языке Swift 4 автоматически получают одинаковый уровень доступа для отдельных случаев перечисления. Рассмотрим, например, чтобы получить доступ к имени ученика и отметкам, защищенным в трех предметах, перечисление имя объявлено как студент, а члены, присутствующие в классе перечисления, - это имя, которое принадлежит строковому типу данных, отметки представлены как mark1, mark2 и mark3 типа данных Integer. Для доступа к имени студента или набранным им оценкам. Теперь переключатель case напечатает имя студента, если этот блок case будет выполнен, иначе он напечатает отметки, полученные студентом. Если оба условия не выполняются, будет выполнен блок по умолчанию.

Контроль доступа для подклассов

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

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}

internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.printIt()

let tennisinstance = tennis()
tennisinstance.printIt()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Контроль доступа к константам, переменным, свойствам и индексам

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

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

private var privateInstance = SomePrivateClass()

Геттеры и сеттеры

Геттеры и сеттеры для констант, переменных, свойств и индексов автоматически получают тот же уровень доступа, что и константа, переменная, свойство или индекс, которым они принадлежат.

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Контроль доступа для инициализаторов и инициализаторов по умолчанию

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

Чтобы объявить каждый подкласс ключевого слова initialize 'required', необходимо определить перед функцией init ().

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

10
30
10

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

Контроль доступа к протоколам

Когда мы определяем новый протокол для наследования функциональных возможностей существующего протокола, оба должны быть объявлены с одинаковыми уровнями доступа для наследования свойств друг друга. Контроль доступа Swift 4 не позволяет пользователям определять «общедоступный» протокол, наследующий от «внутреннего» протокола.

public protocol tcpprotocol {
   init(no1: Int)
}
public class mainClass {
   var no1: Int      // local storage
   init(no1: Int) {
      self.no1 = no1 // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

res is: 20
res is: 30
res is: 50

Контроль доступа для расширений

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

Контроль доступа для дженериков

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

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

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Контроль доступа для псевдонимов типов

Пользователь может определять псевдонимы типов для обработки отдельных типов управления доступом. Один и тот же уровень доступа или разные уровни доступа могут быть определены пользователем. Когда псевдоним типа является «частным», его связанные члены могут быть объявлены как «частные, внутренние из общедоступного типа». Когда псевдоним типа является общедоступным, члены не могут быть псевдонимом как «внутреннее» или «частное» имя.

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

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
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: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
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
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

Когда мы запускаем вышеуказанную программу с помощью игровой площадки, мы получаем следующий результат:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Быстрое кодирование и декодирование

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

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

Обратите внимание, что Langauage соответствует протоколу Codable. Теперь мы преобразуем его в представление данных Json, используя одну простую строку.

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift автоматически закодирует все значения внутри вашего типа данных.

Вы можете декодировать данные с помощью функции декодера, например

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

И JSONEncoder, и его аналог списка свойств PropertyListEncoder имеют множество опций для настройки того, как они работают.