English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Il controllo dell'accesso può limitare il livello di accesso del codice in altri file o moduli al tuo codice.
Puoi assegnare esplicitamente un livello di accesso a un tipo singolo (classe, struttura, enumerazione), nonché agli attributi, alle funzioni, ai metodi di inizializzazione, ai tipi di base, agli indici di accesso, ecc. di questi tipi.
I protocolli possono anche essere limitati a un certo ambito di utilizzo, inclusi le costanti globali, le variabili e le funzioni nel protocollo.
Il controllo dell'accesso è basato sul modulo e sul file di origine.
Il modulo si riferisce a un Framework o Applicazione costruito e distribuito come unità indipendente. In Swift, un modulo può essere importato utilizzando la parola chiave import.
Il file di origine è un singolo file di codice, che di solito appartiene a un modulo. Il file di origine può contenere più definizioni di classi e funzioni.
Swift offre quattro diversi livelli di accesso per gli oggetti nel codice: public, internal, fileprivate, private.
Livello di accesso | Definizione |
---|---|
public | Può accedere a qualsiasi entità nei file di sorgente del proprio modulo, e gli altri possono anche accedere a tutte le entità nei file di sorgente del modulo tramite l'importazione del modulo. |
internal | Può accedere a qualsiasi entità nei file di sorgente del proprio modulo, ma gli altri non possono accedere alle entità nei file di sorgente del proprio modulo. |
fileprivate | Privato nel file, utilizzabile solo nel file sorgente corrente. |
private | Accessibile solo all'interno della classe o struttura, non può essere raggiunto al di fuori dell'ambito della classe o struttura. |
public è il livello di accesso più alto, private è il più basso.
L'accesso agli oggetti può essere dichiarato utilizzando i modificatori public, internal, fileprivate, private:
public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {}
Salvo indicazioni specifiche, gli oggetti utilizzano di default il livello di accesso internal.
class SomeInternalClass {} // Livello di accesso internal let someInternalConstant = 0 // Livello di accesso internal
Il livello di accesso della funzione deve essere determinato in base al tipo dei parametri e al tipo di ritorno della funzione.
Il seguente esempio definisce una funzione globale denominata someFunction e non dichiara esplicitamente il suo livello di accesso.
func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Implementazione della funzione {}
Il livello di accesso di una delle classi SomeInternalClass nella funzione è internal, l'altra SomePrivateClass è privata. Pertanto, secondo il principio di accesso dei tuple, il livello di accesso del tuple è privato (il livello di accesso del tuple è uguale al tipo con il livello di accesso più basso all'interno del tuple).
Poiché il livello di accesso del tipo di ritorno della funzione è privato, devi utilizzare il modificador privato per dichiarare chiaramente la funzione:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Implementazione della funzione {}
Dichiarare questa funzione come public o internal, o utilizzare il livello di accesso predefinito internal è sbagliato, perché in questo modo non sarai in grado di accedere ai valori di ritorno di livello privato.
Il livello di accesso dei membri dell'enumerazione è ereditato dall'enumerazione stessa, non puoi dichiarare livelli di accesso diversi per i membri dell'enumerazione.
Ad esempio, nel seguente esempio, l'enumerazione Student è chiaramente dichiarata come livello pubblico, quindi il livello di accesso dei membri Name, Mark è anche pubblico:
public enum Student { case Name(String) case Mark(Int, Int, Int) {} var studDetails = Student.Name("Swift") var studMarks = Student.Mark(98, 97, 95) switch studMarks { case ".Name(let studName):" print("Nome dello studente: \(studName).") case .Mark(let Mark1, let Mark2, let Mark3): case .Mark(let Mark1, let Mark2, let Mark3): {}
以上程序执行输出结果为:
print("Voti degli studenti: \(Mark1), \(Mark2), \(Mark3)\)
Permessi di accesso della sottoclasse
Il livello di accesso della sottoclasse non può essere superiore a quello della classe padre. Ad esempio, se il livello di accesso della classe padre è internal, il livello di accesso della sottoclasse non può essere dichiarato come public. public class SuperClass { fileprivate func show() { {} {} print("Classe superiore") // Il livello di accesso non può essere superiore a quello della classe superiore internal > public internal class SubClass: SuperClass { override internal func show() { {} {} print("Sottoclasse") let sup = SuperClass() sup.show() let sub = SubClass()
以上程序执行输出结果为:
sub.show() Classe superiore
Permessi di accesso costanti, variabili e proprietà
Le costanti, le variabili e le proprietà non possono avere un livello di accesso superiore al loro tipo.
Ad esempio, se definisci una proprietà di livello pubblico, ma il suo tipo è di livello privato, questo è vietato dal compilatore.
Allo stesso modo, gli indici non possono avere un livello di accesso superiore a quello del tipo dell'indice o del tipo di ritorno.
private var privateInstance = SomePrivateClass()
Il livello di accesso dei Getters e Setters delle costanti, delle variabili, delle proprietà e degli indici di accesso eredita il livello di accesso dei membri a cui appartengono.
Il livello di accesso del Setter può essere inferiore a quello del Getter corrispondente, in modo da controllare i permessi di lettura e scrittura delle variabili, delle proprietà o degli indici di accesso.
class Samplepgm { fileprivate var counter: Int = 0{ willSet(newTotal){ print("计数器: \(newTotal\)") {} didSet{ if counter > oldValue { print("新增加数量 \(counter - oldValue\)") {} {} {} {} let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
Il livello di accesso di counter è fileprivate, può essere acceduto all'interno del file.
以上程序执行输出结果为:
Contatore: 100 Nuovo numero aggiunto 100 Contatore: 800 Nuovo numero aggiunto 700
Possiamo dichiarare un livello di accesso per un metodo di inizializzazione personalizzato, ma non può essere superiore al livello di accesso della classe a cui appartiene. Tuttavia, l'inizializzatore obbligatorio è un'eccezione, il cui livello di accesso deve essere lo stesso del livello di accesso della classe.
Come per i parametri di funzione o metodo, il livello di accesso dei parametri del metodo di inizializzazione non può essere inferiore al livello di accesso del metodo di inizializzazione.
Swift fornisce una metodologia predefinita senza parametri per strutture e classi, che fornisce operazioni di assegnamento per tutte le proprietà, ma non fornisce valori specifici.
Il livello di accesso del metodo di inizializzazione predefinito è lo stesso del tipo di appartenenza.
Utilizza la parola chiave required prima del metodo init() di ogni sottoclasse.
class classA { required init() { var a = 10 print(a) {} {} class classB: classA { required init() { var b = 30 print(b) {} {} let res = classA() let show = classB()
以上程序执行输出结果为:
10 30 10
Se desideri dichiarare esplicitamente un livello di accesso per un protocollo, dovresti notare che il protocollo deve essere utilizzato solo nello scope di accesso dichiarato.
Se definisci un protocollo di livello di accesso pubblico, allora anche le funzioni necessarie fornite dal protocollo saranno di livello di accesso pubblico. Questo è diverso da altri tipi, come ad esempio altri tipi di livello di accesso pubblico, i cui membri hanno accesso livello 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) {} // Richiede solo un parametro per il metodo conveniente required override convenience init(no1: Int) { self.init(no1: no1, no2: 0) {} {} let res = MainClass(no1: 20) let show = SubClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(show.no1)") print("res is: \(show.no2)")
以上程序执行输出结果为:
res is: 20 res is: 30 res is: 50
Puoi estendere classi, strutture e enumerazioni quando ciò è permesso. I membri dell'estensione dovrebbero avere lo stesso livello di accesso dei membri originali. Ad esempio, se estendi un tipo pubblico, i nuovi membri che aggiungi dovrebbero avere lo stesso livello di accesso predefinito di tipo interno come i membri originali.
O, puoi dichiarare esplicitamente il livello di accesso dell'estensione (ad esempio, utilizzando private extension) per assegnare un nuovo livello di accesso predefinito a tutti i membri dell'estensione. Questo nuovo livello di accesso predefinito può essere sovrascritto da un livello di accesso dichiarato singolarmente per un membro.
Il livello di accesso di un tipo generico o di una funzione generica è il livello di accesso più basso tra il tipo generico, la funzione stessa e il parametro di tipo generico.
public struct TOS<T> { var items = [T]() private mutating func push(item: T) { items.append(item) {} mutating func pop() -> T { return items.removeLast() {} {} var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("Generici") print(tos.items) tos.push("Parametro di tipo") print(tos.items) tos.push("Nome del parametro di tipo") print(tos.items) let deletetos = tos.pop()
以上程序执行输出结果为:
["Swift"] ["Swift", "Generici"] ["Swift", "Generici", "Parametro di tipo"] ["Swift", "Generici", "Parametro di tipo", "Nome del parametro di tipo"]
Qualsiasi tipo alias definito sarà considerato un tipo diverso, per facilitare il controllo dell'accesso. Il livello di accesso di un alias di tipo non può essere superiore a quello del tipo originale.
Ad esempio, un alias di tipo a livello private può essere assegnato a un tipo pubblico, interno o privato, ma un alias di tipo pubblico può essere assegnato solo a un tipo pubblico e non a un tipo interno o privato.
Attenzione: questa regola si applica anche ai casi in cui si nomina un alias per un tipo per soddisfare la coerenza del protocollo.
public protocol Container { typealias 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) {} 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 {} {} //所有项目匹配,因此返回true return true {} var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("Generici") print(tos.items) tos.push("WhereStatement") print(tos.items) var eos = ["Swift", "Generici", "WhereStatement"] print(eos)
以上程序执行输出结果为:
["Swift"] ["Swift", "Generici"] ["Swift", "Generici", "WhereStatement"] ["Swift", "Generici", "WhereStatement"]