Swift - kontrola dostępu
Ograniczenie dostępu do bloków kodu, modułów i abstrakcji odbywa się poprzez kontrolę dostępu. Dostęp do klas, struktur i wyliczeń można uzyskać zgodnie z ich właściwościami, metodami, inicjatorami i indeksami dolnymi za pomocą mechanizmów kontroli dostępu. Stałe, zmienne i funkcje w protokole są ograniczone i mają dostęp globalny i lokalny poprzez kontrolę dostępu. Kontrola dostępu zastosowana do właściwości, typów i funkcji może być określana jako „jednostki”.
Model kontroli dostępu oparty jest na modułach i plikach źródłowych.
Moduł jest zdefiniowany jako pojedyncza jednostka dystrybucji kodu i można go zaimportować za pomocą słowa kluczowego „import”. Plik źródłowy jest definiowany jako pojedynczy plik kodu źródłowego z modułem umożliwiającym dostęp do wielu typów i funkcji.
Język Swift 4 zapewnia trzy różne poziomy dostępu. Dostęp do nich jest publiczny, wewnętrzny i prywatny.
S.Nr | Poziomy dostępu i definicja |
---|---|
1 | Public Umożliwia przetwarzanie jednostek w dowolnym pliku źródłowym z ich modułu definiującego, pliku źródłowego z innego modułu, który importuje moduł definiujący. |
2 | Internal Umożliwia używanie jednostek w dowolnym pliku źródłowym z ich modułu definiującego, ale nie w żadnym pliku źródłowym poza tym modułem. |
3 | Private Ogranicza użycie jednostki do jej własnego definiującego pliku źródłowego. Dostęp prywatny odgrywa rolę w ukryciu szczegółów implementacji określonej funkcjonalności kodu. |
Składnia
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
Kontrola dostępu dla typów funkcji
Niektóre funkcje mogą mieć argumenty zadeklarowane wewnątrz funkcji bez zwracanych wartości. Poniższy program deklaruje a i b jako argumenty funkcji sum (). Wewnątrz samej funkcji wartości argumentów a i b są przekazywane przez wywołanie funkcji sum (), a jej wartości są drukowane, co eliminuje zwracane wartości. Aby ustawić zwracany typ funkcji jako prywatny, zadeklaruj ogólny poziom dostępu funkcji z prywatnym modyfikatorem.
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)
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
30 20
50 40
30 24
Kontrola dostępu dla typów wyliczeniowych
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).")
}
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
Student Marks are: 98,97,95
Wyliczanie w języku Swift 4 automatycznie otrzymuje ten sam poziom dostępu dla poszczególnych przypadków wyliczenia. Rozważmy na przykład, aby uzyskać dostęp do nazwisk uczniów i ocen zabezpieczonych w trzech przedmiotach wyliczenie nazwa jest zadeklarowana jako student, a członkowie obecni w klasie enum to nazwa należąca do typu string, znaki są reprezentowane jako mark1, mark2 i mark3 typu danych Integer. Aby uzyskać dostęp do nazwiska ucznia lub ocen, które otrzymali. Teraz obudowa przełącznika wydrukuje nazwisko ucznia, jeśli ten blok przypadku zostanie wykonany, w przeciwnym razie wydrukuje znaki zabezpieczone przez ucznia. Jeśli oba warunki zawiodą, zostanie wykonany blok domyślny.
Kontrola dostępu dla podklas
Swift 4 umożliwia użytkownikowi tworzenie podklas dowolnej klasy, do której można uzyskać dostęp w bieżącym kontekście dostępu. Podklasa nie może mieć wyższego poziomu dostępu niż jej nadklasa. Użytkownikowi nie wolno pisać publicznej podklasy wewnętrznej nadklasy.
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()
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
Welcome to Swift Super Class
Welcome to Swift Sub Class
Kontrola dostępu do stałych, zmiennych, właściwości i indeksów
Stała, zmienna lub właściwość Swift 4 nie może być zdefiniowana jako publiczna niż jej typ. Nie można pisać własności publicznej o typie prywatnym. Podobnie, indeks dolny nie może być bardziej publiczny niż jego indeks lub typ zwracany.
Gdy stała, zmienna, właściwość lub indeks dolny używają typu prywatnego, stała, zmienna, właściwość lub indeks dolny również muszą być oznaczone jako prywatne -
private var privateInstance = SomePrivateClass()
Getters i Setters
Metody pobierające i ustawiające dla stałych, zmiennych, właściwości i indeksów dolnych automatycznie otrzymują ten sam poziom dostępu co stała, zmienna, właściwość lub indeks dolny, do których należą.
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
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Kontrola dostępu dla inicjatorów i domyślnych inicjatorów
Inicjatorom niestandardowym można przypisać poziom dostępu mniejszy lub równy typowi, który inicjują. Wymagany inicjator musi mieć ten sam poziom dostępu, co klasa, do której należy. Typy parametrów inicjatora nie mogą być bardziej prywatne niż własny poziom dostępu inicjatora.
Aby zadeklarować każdą podklasę słowa kluczowego „required” inicjalizacji, należy zdefiniować ją przed funkcją 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()
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
10
30
10
Domyślny inicjator ma ten sam poziom dostępu, co typ, który inicjuje, chyba że ten typ jest zdefiniowany jako publiczny. Gdy domyślna inicjalizacja jest zdefiniowana jako publiczna, jest traktowana jako wewnętrzna. Gdy użytkownik potrzebuje, aby typ publiczny był inicjalizowany za pomocą inicjatora bez argumentów w innym module, należy jawnie podać publiczny inicjator bez argumentów jako część definicji typu.
Kontrola dostępu do protokołów
Kiedy definiujemy nowy protokół w celu dziedziczenia funkcjonalności z istniejącego protokołu, oba muszą mieć te same poziomy dostępu, aby dziedziczyć swoje właściwości. Kontrola dostępu Swift 4 nie pozwoli użytkownikom na zdefiniowanie protokołu „publicznego”, który dziedziczy po protokole „wewnętrznym”.
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)")
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
res is: 20
res is: 30
res is: 50
Kontrola dostępu do rozszerzeń
Swift 4 nie pozwala użytkownikom na zapewnienie jawnego modyfikatora poziomu dostępu dla rozszerzenia, gdy użytkownik używa tego rozszerzenia w celu dodania zgodności z protokołem. Domyślny poziom dostępu dla każdej implementacji wymagań protokołu w ramach rozszerzenia ma własny poziom dostępu do protokołu.
Kontrola dostępu dla typów generycznych
Generics pozwalają użytkownikowi określić minimalne poziomy dostępu, aby uzyskać dostęp do ograniczeń typu w jego parametrach typu.
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()
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Kontrola dostępu dla aliasów typów
Użytkownik może zdefiniować aliasy typów, aby traktować różne typy kontroli dostępu. Użytkownik może zdefiniować ten sam poziom dostępu lub różne poziomy dostępu. Gdy alias typu jest „prywatny”, skojarzone z nim elementy członkowskie można zadeklarować jako „prywatne, wewnętrzne typu publicznego”. Gdy alias typu jest publiczny, członkowie nie mogą być aliasami jako nazwą „wewnętrzną” ani „prywatną”
Wszystkie zdefiniowane aliasy typów są traktowane jako odrębne typy na potrzeby kontroli dostępu. Alias typu może mieć poziom dostępu mniejszy lub równy poziomowi dostępu typu, do którego jest przypisany. Na przykład alias typu prywatnego może aliasować typ prywatny, wewnętrzny lub publiczny, ale alias typu publicznego nie może aliasować typu wewnętrznego ani prywatnego.
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)
Gdy uruchomimy powyższy program za pomocą placu zabaw, otrzymamy następujący wynik -
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Szybkie kodowanie i dekodowanie
Swift 4 wprowadza nowy Codable Protokół, który umożliwia serializację i de-serializację niestandardowych typów danych bez pisania specjalnego kodu - i bez martwienia się o utratę typów wartości.
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
Zauważ, że Langauage jest zgodny z protokołem Codable. Teraz przekonwertujemy go na reprezentację danych Json za pomocą jednej prostej linii.
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
//Perform some operations on this value.
}
Swift automatycznie zakoduje wszystkie wartości w Twoim typie danych.
Możesz dekodować dane za pomocą funkcji dekodera, takiej jak
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
//Perform some operations on this value.
}
Zarówno JSONEncoder, jak i jego odpowiednik PropertyListEncoder z listą właściwości mają wiele opcji dostosowywania sposobu ich działania.