Swift - Контроль доступа
Ограничение доступа к кодовым блокам, модулям и абстракциям осуществляется посредством управления доступом. Доступ к классам, структурам и перечислениям можно получить в соответствии с их свойствами, методами, инициализаторами и индексами с помощью механизмов контроля доступа. Константы, переменные и функции в протоколе ограничены и разрешен доступ как глобальный, так и локальный посредством управления доступом. Контроль доступа, применяемый к свойствам, типам и функциям, может называться «сущностями».
Модель контроля доступа основана на модулях и исходных файлах.
Модуль определяется как единая единица распространения кода и может быть импортирован с помощью ключевого слова 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 имеют множество опций для настройки того, как они работают.