English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Swift Access Control

Access control can limit the access level of code in other source files or modules to your code.

You can explicitly set the access level for a single type (class, structure, enumeration), as well as for properties, functions, initialization methods, basic types, and index subscripts of these types.

Protocols can also be limited to a certain range of use, including global constants, variables, and functions within the protocol.

Access control is based on modules and source files.

A module refers to a Framework or Application built and released as an independent unit. In Swift, a module can use the import keyword to introduce another module.

A source file is a single source code file, which usually belongs to a module. A source file can contain multiple class and function definitions.

Swift provides four different access levels for entities in code: public, internal, fileprivate, and private.

Access levelDefinition
publicCan access any entity in the source files of its own module, and others can also access all entities in the source files by importing the module.
internalCan access any entity in the source files of its own module, but others cannot access the entities in the source files of the module.
fileprivatePrivate within the file, can only be used within the current source file.
privateCan only be accessed within the class, and cannot be accessed outside the scope of the class or structure.

public ist der höchste Zugriffsgrad, private der niedrigste Zugriffsgrad.

Syntax

Die Zugriffsstufe der Entitäten wird durch Modifikatoren wie public, internal, fileprivate und private angegeben:

Online-Beispiel

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() {}

Es sei denn, es gibt besondere Erklärungen, sonst werden die Entitäten mit dem Standardzugriffsgrad internal verwendet.

Standardmäßig ist der Zugriffsgrad internal, wenn keine Zugriffsstufe angegeben ist.

class SomeInternalClass {}              // Zugriffsgrad internal
let someInternalConstant = 0            // Zugriffsgrad internal

Zugriffsrechte der Funktionstypen

Der Zugriffsgrad der Funktion muss auf der Grundlage des Zugriffsgrades der Parameter- und Rückgabetypen der Funktion ermittelt werden.

Das folgende Beispiel definiert eine globale Funktion namens someFunction und erklärt ihren Zugriffsgrad nicht explizit.

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // Funktionserstellung
{}

Der Zugriffsgrad einer der Klassen SomeInternalClass ist internal, der Zugriffsgrad der anderen SomePrivateClass ist private. Daher ist der Zugriffsgrad dieses Tuples aufgrund des Grundsatzes der Zugriffsstufen des Tuples private (der Zugriffsgrad des Tuples stimmt mit dem Zugriffsgrad des Typs mit der niedrigsten Zugriffsstufe im Tuple überein).

Da der Zugriffsgrad des Rückgabetyps der Funktion private ist, müssen Sie den privaten Modifikator verwenden und die Funktion klar deklarieren:

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // Funktionserstellung
{}

Es ist falsch, die Funktion als public oder internal zu deklarieren oder den Standardzugriffsniveau internal zu verwenden, da Sie auf private Zugriffsstufen der Rückgabewerte nicht zugreifen können.

Zugriffsrechte von Enum-Typen

Die Zugriffsstufen der Mitglieder der Enumeration erben von der Enumeration selbst, Sie können die Zugriffsstufen der Mitglieder der Enumeration nicht单独申明不同的访问级别.

Online-Beispiel

Zum Beispiel im folgenden Beispiel ist die Enumeration Student ausdrücklich als public-Stufe deklariert, daher sind die Zugriffsstufen der Mitglieder Name, Mark ebenfalls public:

Online-Beispiel

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("Schülername: (studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("Schülernoten: (Mark1),(Mark2),(Mark3)
{}

The output of the above program is as follows:

Schülernoten: 98,97,95

Zugriffsrechte der Unterklasse

Der Zugriffsgrad der Unterklasse darf nicht höher als der der Oberklasse sein. Zum Beispiel, wenn der Zugriffsgrad der Oberklasse internal ist, kann der Zugriffsgrad der Unterklasse nicht als public deklariert werden.

Online-Beispiel

 public class SuperClass {
    fileprivate func show() {
        print("Überklasse")
    {}
{}
 
// Der Zugriffsgrad darf nicht höher als der der Überklasse sein internal > public
internal class SubClass: SuperClass {
    override internal func show() {
        print("Unterklasse")
    {}
{}
 
let sup = SuperClass()
sup.show()
 
let sub = SubClass()
sub.show()

The output of the above program is as follows:

Überklasse
Unterklasse

Zugriffsrechte von Konstanten, Variablen, Eigenschaften und Indexen

Konstanten, Variablen und Eigenschaften können keine höhere Zugriffsstufe als ihr Typ haben.

Zum Beispiel, wenn Sie eine Eigenschaft mit öffentlicher Stufe definieren, aber deren Typ private ist, ist dies dem Compiler nicht erlaubt.

Gleichzeitig kann der Index keine höhere Zugriffsstufe als der Index- oder Rückgabetyp haben.

Wenn die Definitionstypen von Konstanten, Variablen, Eigenschaften und Indexindizes private sind, müssen sie unbedingt den Zugriffsebene als private deklarieren:

private var privateInstance = SomePrivateClass()

Getter- und Setter-Zugriffsrechte

Die Zugriffsstufe der Getters und Setters von Konstanten, Variablen, Attributen und Indexen wird von der Zugriffsstufe der zugewiesenen Member geerbt.

Der Zugriffsgrad des Setters kann niedriger als der des correspondingen Getters sein, so dass die Lese- und Schreibrechte von Variablen, Attributen oder Indexen gesteuert werden können.

Online-Beispiel

class Samplepgm {
    fileprivate var counter: Int = 0{
        willSet(newTotal){
            print("Zähler: (newTotal)")
        {}
        didSet{
            if counter > oldValue {
                print("Neu hinzugefügter Wert (counter - oldValue)")
            {}
        {}
    {}
{}
 
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Der Zugriffsgrad von counter ist fileprivate, er ist im Dateiinneren zugänglich.

The output of the above program is as follows:

Zähler: 100
Neu hinzugefügter Wert 100
Zähler: 800
Neu hinzugefügter Wert 700

Konstruktor- und Standardkonstruktor-Zugriffsrechte

Initialisierung

Wir können die Zugriffsstufe der eigenen Initialisierungsmethode angeben, aber sie darf nicht höher als die Zugriffsstufe der zugewiesenen Klasse sein. Ausnahme ist der erforderliche Konstruktor, dessen Zugriffsstufe gleich der Zugriffsstufe der zugewiesenen Klasse sein muss.

Wie bei Funktions- oder Methodenparametern kann die Zugriffsstufe der Initialisierungsmethodenparameter nicht niedriger als die Zugriffsstufe der Initialisierungsmethode selbst sein.

Standardinitialisierungsmethode

Swift bietet für Strukturen und Klassen eine Standardinitialisierungsmethode ohne Parameter an, um allen Attributen Werte zuzuweisen, aber keine spezifischen Werte zu geben.

Die Zugriffsstufe der Standardinitialisierungsmethode ist gleich der Zugriffsstufe des zugewiesenen Typs.

Online-Beispiel

Verwenden Sie vor jedem init() -Methoden der Unterklasse den Schlüsselwort required, um den Zugriffsrechten zu erklären.

Online-Beispiel

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()

The output of the above program is as follows:

10
30
10

Protokoll-Zugriffsrechte

Wenn Sie die Zugriffsstufe eines Protokolls explizit angeben möchten, müssen Sie darauf achten, dass das Protokoll nur im angegebenen Zugriffsstufenbereich verwendet wird.

Wenn Sie eine öffentliche Zugriffsstufe für ein Protokoll definieren, dann sind auch die notwendigen Funktionen, die das Protokoll bereitstellt, öffentlich zugänglich. Dies unterscheidet sich von anderen Typen, wie z.B. anderen Typen mit öffentlicher Zugriffsstufe, deren Member-Zugriffsstufe intern ist.

Online-Beispiel

public protocol TcpProtocol {
    init(no1: Int)
{}
 
public class MainClass {
    var no1: Int // Lokale Speicherung
    init(no1: Int) {
        self.no1 = no1 // Initialisierung
    {}
{}
 
class SubClass: MainClass, TcpProtocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    {}
    
    // Erfordert nur einen Parameter für den bequemen Methoden
    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.no"1)
print("res is: \(show.no"1)
print("res is: \(show.no"2)

The output of the above program is as follows:

res is: 20
res is: 30
res is: 50

Erweiterungs-zugriffsrechte

Sie können Klassen, Strukturen und Enumerationen unter bestimmten Bedingungen erweitern. Die Erweiterungsmitglieder sollten die gleiche Zugriffsrechte wie die ursprünglichen Klassenmitglieder haben. Zum Beispiel, wenn Sie eine öffentliche Typ erweitern, dann sollten die neuen Mitglieder die gleiche Standardzugriffsrechte wie die ursprünglichen Mitglieder haben.

Oder Sie können die Zugriffsrechte der Erweiterung ausdrücklich angeben (z.B. mit private extension), um allen Mitgliedern der Erweiterung eine neue Standardzugriffsrechte zuweisen. Diese neue Standardzugriffsrechte kann von den einzeln angegebenen Zugriffsrechten eines Mitglieds übergangen werden.

Generische Zugriffsrechte

Der Zugriffsniveau von generischen Typen oder generischen Funktionen ist das niedrigste von den drei: dem generischen Typ, der Funktion selbst und den generischen Typparametern.

Online-Beispiel

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("Generics")
print(tos.items)
 
tos.push("Typparameter")
print(tos.items)
 
tos.push("Typparametername")
print(tos.items)
let deletetos = tos.pop()

The output of the above program is as follows:

["Swift"]
["Swift", "Generics"]
["Swift", "Generische", "Typparameter"]
["Swift", "Generische", "Typparameter", "Typparametername"]

Typalias

Jegliche von Ihnen definierte Typalias wird als ein anderer Typ behandelt, um den Zugriff zu steuern. Der Zugriffsniveau einer Typalias kann nicht höher als das der ursprünglichen Typ sein.

Zum Beispiel kann ein privater Typalias einem public, internal oder privaten Typ zugewiesen werden, aber ein publicer Typalias kann nur einem publicen Typ zugewiesen werden und nicht einem internalen oder privaten Typ.

Hinweis: Dieses Regel gilt auch für die Benennung von Aliassen für Typen, um Protokollkonformität zu gewährleisten.

Online-Beispiel

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> Implementierung
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    {}
    
    mutating func pop() -> T {
        return items.removeLast()
    {}
    
    // Konformität zum Container-Protokoll
    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
    wo C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, anotherContainer: C2) -> Bool {
        // Überprüfen Sie, dass beide Container die gleiche Anzahl von Elementen enthalten
        Wenn someContainer.count != anotherContainer.count {
            return false
        {}
        
        // Überprüfen Sie jedes Paar von Elementen, um zu sehen, ob sie äquivalent sind
        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("Swift")
print(tos.items)
 
tos.push("Generics")
print(tos.items)
 
tos.push("Where Clause")
print(tos.items)
 
var eos = ["Swift", "Generics", "Where Clause"]
print(eos)

The output of the above program is as follows:

["Swift"]
["Swift", "Generics"]
["Swift", "Generics", "Where Clause"]
["Swift", "Generics", "Where Clause"]