Swift - Controllo degli accessi
Per limitare l'accesso a blocchi di codice, moduli e astrazione viene eseguito tramite il controllo degli accessi. È possibile accedere a classi, strutture ed enumerazioni in base alle loro proprietà, metodi, inizializzatori e pedici tramite meccanismi di controllo dell'accesso. Costanti, variabili e funzioni in un protocollo sono limitate e consentito l'accesso come globale e locale attraverso il controllo dell'accesso. Il controllo dell'accesso applicato a proprietà, tipi e funzioni può essere definito "entità".
Il modello di controllo dell'accesso si basa su moduli e file di origine.
Il modulo è definito come una singola unità di distribuzione del codice e può essere importato utilizzando la parola chiave "import". Un file sorgente è definito come un singolo file di codice sorgente con in un modulo per accedere a più tipi e funzioni.
Tre diversi livelli di accesso sono forniti dalla lingua Swift 4. Sono accesso pubblico, interno e privato.
S.No | Livelli di accesso e definizione |
---|---|
1 | Public Consente alle entità di essere elaborate con qualsiasi file sorgente dal loro modulo di definizione, un file sorgente da un altro modulo che importa il modulo di definizione. |
2 | Internal Consente alle entità di essere utilizzate all'interno di qualsiasi file sorgente dal loro modulo di definizione, ma non in alcun file sorgente al di fuori di quel modulo. |
3 | Private Limita l'uso di un'entità al proprio file di origine di definizione. L'accesso privato gioca il ruolo di nascondere i dettagli di implementazione di una funzionalità di codice specifica. |
Sintassi
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
Controllo degli accessi per i tipi di funzione
Alcune funzioni possono avere argomenti dichiarati all'interno della funzione senza alcun valore di ritorno. Il seguente programma dichiara aeb come argomenti della funzione sum (). All'interno della funzione stessa i valori per gli argomenti aeb vengono passati invocando la chiamata della funzione sum () ei suoi valori vengono stampati eliminando così i valori di ritorno. Per rendere privato il tipo di ritorno della funzione, dichiara il livello di accesso generale della funzione con il modificatore 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)
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
30 20
50 40
30 24
Controllo di accesso per i tipi di enumerazione
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).")
}
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
Student Marks are: 98,97,95
L'enumerazione nella lingua Swift 4 riceve automaticamente lo stesso livello di accesso per i singoli casi di un'enumerazione. Si consideri ad esempio per accedere al nome degli studenti e ai voti assicurati in tre materie il nome dell'enumerazione è dichiarato come studente e i membri presenti in enum class sono il nome che appartiene al tipo di dati stringa, i voti sono rappresentati come mark1, mark2 e mark3 del tipo di dati Integer. Per accedere al nome dello studente o ai voti che hanno ottenuto. Ora, lo switch case stamperà il nome dello studente se quel blocco di case viene eseguito altrimenti stamperà i voti garantiti dallo studente. Se entrambe le condizioni falliscono, verrà eseguito il blocco predefinito.
Controllo degli accessi per le sottoclassi
Swift 4 consente all'utente di sottoclassare qualsiasi classe a cui è possibile accedere nel contesto di accesso corrente. Una sottoclasse non può avere un livello di accesso più alto della sua superclasse. L'utente non può scrivere una sottoclasse pubblica di una superclasse interna.
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()
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Controllo dell'accesso per costanti, variabili, proprietà e pedici
La costante, la variabile o la proprietà di Swift 4 non può essere definita pubblica rispetto al suo tipo. Non è valido scrivere una proprietà pubblica con un tipo privato. Allo stesso modo, un pedice non può essere più pubblico del suo indice o tipo restituito.
Quando una costante, una variabile, una proprietà o un pedice utilizza un tipo privato, anche la costante, la variabile, la proprietà o il pedice devono essere contrassegnati come privati:
private var privateInstance = SomePrivateClass()
Getters e Setter
Getter e setter per costanti, variabili, proprietà e pedici ricevono automaticamente lo stesso livello di accesso della costante, variabile, proprietà o pedice a cui appartengono.
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
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Controllo dell'accesso per inizializzatori e inizializzatori predefiniti
Agli inizializzatori personalizzati può essere assegnato un livello di accesso inferiore o uguale al tipo che inizializzano. Un inizializzatore richiesto deve avere lo stesso livello di accesso della classe a cui appartiene. I tipi di parametri di un inizializzatore non possono essere più privati del livello di accesso proprio dell'inizializzatore.
Per dichiarare ogni sottoclasse della parola chiave initialize 'required' deve essere definita prima della funzione 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()
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
10
30
10
Un inizializzatore predefinito ha lo stesso livello di accesso del tipo che inizializza, a meno che quel tipo non sia definito come pubblico. Quando l'inizializzazione predefinita è definita come pubblica, viene considerata interna. Quando l'utente necessita che un tipo pubblico sia inizializzabile con un inizializzatore senza argomenti in un altro modulo, fornire esplicitamente un inizializzatore pubblico senza argomenti come parte della definizione del tipo.
Controllo degli accessi per i protocolli
Quando definiamo un nuovo protocollo per ereditare le funzionalità da un protocollo esistente, entrambi devono essere dichiarati gli stessi livelli di accesso per ereditare le proprietà l'uno dell'altro. Il controllo degli accessi di Swift 4 non consentirà agli utenti di definire un protocollo "pubblico" che eredita da un protocollo "interno".
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)")
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
res is: 20
res is: 30
res is: 50
Controllo degli accessi per le estensioni
Swift 4 non consente agli utenti di fornire un modificatore del livello di accesso esplicito per un'estensione quando l'utente utilizza tale estensione per aggiungere la conformità del protocollo. Il livello di accesso predefinito per ciascuna implementazione dei requisiti di protocollo all'interno dell'estensione viene fornito con il proprio livello di accesso al protocollo.
Controllo degli accessi per i generici
I generici consentono all'utente di specificare i livelli di accesso minimi per accedere ai vincoli di tipo sui suoi parametri di tipo.
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()
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Controllo dell'accesso per gli alias di tipo
L'utente può definire alias di tipo per trattare tipi di controllo di accesso distinti. Lo stesso livello di accesso o diversi livelli di accesso possono essere definiti dall'utente. Quando l'alias di tipo è "privato", i membri associati possono essere dichiarati come "privato, interno di tipo pubblico". Quando l'alias di tipo è pubblico, i membri non possono essere alias come nome "interno" o "privato"
Tutti gli alias di tipo definiti dall'utente vengono trattati come tipi distinti ai fini del controllo dell'accesso. Un alias di tipo può avere un livello di accesso inferiore o uguale al livello di accesso del tipo alias. Ad esempio, un alias di tipo privato può alias un tipo privato, interno o pubblico, ma un alias di tipo pubblico non può alias un tipo interno o privato.
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)
Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Codifica e decodifica rapide
Swift 4 introduce un nuovo Codable Protocollo, che consente di serializzare e de-serializzare i tipi di dati personalizzati senza scrivere alcun codice speciale e senza doversi preoccupare di perdere i tipi di valore.
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
Si noti che Langauage è conforme al protocollo codificabile. Ora lo convertiremo in una rappresentazione dei dati Json usando una semplice riga.
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
//Perform some operations on this value.
}
Swift codificherà automaticamente tutti i valori all'interno del tuo tipo di dati.
È possibile decodificare i dati utilizzando la funzione Decoder come
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
//Perform some operations on this value.
}
Sia JSONEncoder che la sua controparte PropertyListEncoder dell'elenco delle proprietà hanno molte opzioni per personalizzare il loro funzionamento.