Welche es gibt und wie ich sie persönlich in Projekten einsetze
Die Access Level in Swift steuern seit jeher die Berechtigungen, mit denen sich auf die Code-Fragmente eines Projekts zugreifen lässt. Access Level regeln so unter anderem, ob beispielsweise Properties nur innerhalb eines Typs angesprochen werden können oder auch direkt von Instanzen jenes Typs auslesbar sind. Das nachfolgende Listing skizziert einmal dieses Szenario:
struct Person {
    internal var name: String
    private var address: String?
    init(name: String) {
        self.name = name
    }
    internal func printAddress() {
        guard let address else {
            return
        }
        print(address)
    }
}
var me = Person(name: "Thomas Sillmann")
print(me.name)
// Thomas Sillmann
print(me.address) // Fehler: Kein Zugriff auf address möglich.
Die Eigenschaft name der Structure Person besitzt den Access Level internal. Innerhalb eines Projekts kann sie so problemlos von Instanzen der Structure angesprochen und ausgelesen werden. Anders verhält es sich mit address. address ist als private deklariert und steht so ausschließlich innerhalb der Structure Person selbst zur Verfügung (wie in der Implementierung der Methode printAddress() zu sehen). Ein Zugriff von außen über eine Person-Instanz ist nicht möglich (wie der print-Aufruf am Ende des Listings beispielhaft demonstriert).
Verfügbare Access Level
Nach dieser kleinen Einführung in das Grundprinzip der Access Level stelle ich euch nun einmal die verschiedenen Level und ihre Funktionsweise kurz vor:
private: Das restriktivste Access Level. Alsprivategekennzeichnete Elemente können nur innerhalb des Scopes angesprochen und verwendet werden, in dem sie deklariert sind. Die Propertynameaus dem vorangegangenen Listing steht so nur innerhalb der StructurePersonzur Verfügung.fileprivate: Verhält sich ähnlich wieprivate, weitet den Zugriff aber auf die zugrundeliegende Datei aus. Wärenamealsfileprivategekennzeichnet und ist dasprint-Statement am Ende Teil derselben Swift-Datei, in der auch die StructurePersondeklariert ist, wäre so ein Zugriff aufnamemöglich. Aus anderen Dateien heraus würdenamejedoch dann nicht zur Verfügung stehen.internal: Dieses Access Level ist der Standard und kommt immer automatisch zum Einsatz, wenn kein anderes Access Level explizit angegeben ist. Eine explizite Verwendung voninternal, so wie sie bei der Deklaration dername-Property zum Einsatz kam, ist nicht notwendig, aber möglich.
Mittelsinternallegt man fest, dass das zugehörige Element innerhalb eines Projekts bzw. Moduls zur Verfügung steht. Entwickelt man eine App, steheninternal-Elemente entsprechend innerhalb des gesamten App-Projekts zur Verfügung (sofern man verschiedene Projektteile nicht in separate und unabhängige Module auslagert).public: Dieses Access Level ist typischerweise dann relevant, wenn man beispielsweise ein Framework entwickelt, das als Modul in andere Projekte eingebunden werden soll. Die alspublicgekennzeichneten Elemente stellen dann die öffentliche API des Moduls dar, die aus anderen Projekten, die das Modul einbinden, angesprochen werden kann. Würdet ihr ein Framework entwickeln, dass nur die erstgenannten Access Levelprivate,fileprivateundinternalverwendet, wäre der gesamte Code nicht verwendbar, würde er in Form eines Moduls in einem anderen Projekt eingebunden werden. Es braucht alsopublicum festzulegen, welche Teile eines Moduls aus anderen Projekten heraus nutzbar sind.
Wichtig hierbei: Alspublicgekennzeichnete Klassen, Properties und Methoden können zwar in anderen Modulen verwendet, aber nicht überschrieben werden. Es lassen sich demnach keine Subklassen dieser Elemente erzeugen oder Properties und Methoden überschreiben.open:openstellt das am wenigsten restriktive Access Level dar und verhält sich im Grunde ähnlich wiepublic, es ist also bei der Deklaration der öffentlichen API von Modulen relevant. Im Gegensatz zupublicermöglicht esopenjedoch, Subklassen zu erstellen und Properties sowie Methoden zu überschreiben. Setzt manopenein, muss man also bedanken, dass Nutzer die zugrundeliegende Funktionalität des eigenen Codes erweitern bzw. verändern können. Entsprechend sollte manopennur dann verwenden, wenn solch ein Vorgehen explizit gewünscht ist und nicht zu Problemen bei der sonstigen Funktionalität des zugrundeliegenden Moduls führen kann.
Mein persönlicher Einsatz der Access Level
open und public spielen in meinem persönlichen Entwickler-Alltag so gut wie gar keine Rolle. Das liegt daran, da ich nur sehr selten an Frameworks oder Modulen außerhalb eines spezifischen App-Projekts arbeite. Der Großteil meiner Arbeit findet innerhalb solcher in sich geschlossenen App-Projekte statt, für die open und public schlicht nicht relevant sind. Daher klammere ich diese beiden Access Level an dieser Stelle aus.
Von den übrigen drei Access Leveln nutze ich ausschließlich zwei: internal und private.
internal dürfte nicht wenig überraschend sein. Dieses Standard-Access Level ist zwingend notwendig, um innerhalb eines App-Projekts mit all den verschiedenen Typen, Eigenschaften und Funktionen kommunizieren zu können, die für das Projekt notwendig sind. Für alle Interaktionen von Instanzen untereinander nutze ich so internal und regle damit die Funktionsweise von Apps.
Das andere Extrem stellt private dar. Bei der Deklaration von Typen und deren Properties und Methoden kommt es sehr häufig vor, das einzelne Eigenschaften nur für die Implementierung jenes Typs bestimmt sind und von außen nicht zugänglich sein müssen oder sollen. Genau für diese Zwecke nutze ich private, und das sehr exzessiv. Im Endeffekt gilt: Was nicht internal zu sein braucht, wird private.
Und was ist mit fileprivate? Tatsächlich gab es bisher kaum Anwendungsfälle, in denen fileprivate für mich relevant gewesen wäre. Das hängt sicherlich auch damit zusammen, dass ich meinen Code in der Regel umfangreich auf mehrere Swift-Dateien verteile. So hat jeder Typ meist seine eigene Swift-Datei, Extensions oftmals ebenso. Zugriffe mittels fileprivate dann auf eine spezifische Datei zu begrenzen, bringt in diesen Szenarien nichts und ist funktional identisch zur private-Deklaration (die in meinem Fall dann zum Einsatz käme).
Schreibe einen Kommentar