Was ist ein gutes Beispiel, um in Swift3 zwischen fileprivate und private zu unterscheiden?
142
Dieser Artikel war hilfreich, um die neuen Zugriffsspezifizierer in zu verstehen Swift 3. Es gibt auch einige Beispiele für verschiedene Verwendungen von fileprivateund private.
Meine Frage ist - ist die Verwendung fileprivateeiner Funktion, die nur in dieser Datei verwendet wird, nicht dieselbe wie die Verwendung private?
fileprivateist jetzt das, was privatefrüher in früheren Swift-Versionen war: Zugriff über dieselbe Quelldatei. Auf eine als gekennzeichnete Deklaration privatekann nur innerhalb des lexikalischen Bereichs zugegriffen werden, in dem sie deklariert ist. Sie privateist daher restriktiver als fileprivate.
Ab Swift 4 können Erweiterungen desselben Typs auf private Deklarationen innerhalb eines Typs zugreifen, wenn die Erweiterung in derselben Quelldatei definiert ist.
Beispiel (alles in einer Quelldatei):
class A {privatefunc foo(){}fileprivatefunc bar(){}func baz(){
foo()
bar()}}extension A {func test(){
foo()// Swift 3: error: use of unresolved identifier 'foo'
// Swift 4: no error because extension is in same source file
bar()}}let a = A()
a.foo()// error: 'foo' is inaccessible due to 'private' protection level
a.bar()
Auf die private fooMethode kann nur im Rahmen der class A { ... }Definition zugegriffen werden. Es ist nicht einmal über eine Erweiterung des Typs zugänglich (in Swift 3 finden Sie Änderungen in Swift 4 im zweiten Hinweis unten).
Auf die dateiprivate barMethode kann über dieselbe Quelldatei zugegriffen werden.
Anmerkungen:
Der Vorschlag SE-0159 - Fix Private Access Levels schlug vor, in Swift 4 auf die Swift 2-Semantik zurückzugreifen. Nach einer langen und kontroversen Diskussion über die Mailingliste von swift-evolution wurde der Vorschlag abgelehnt .
Wenn Sie Code automatisch von Swift 2 nach 3 konvertieren, wird Xcode privatezu fileprivate. Wenn Sie jedoch den Luxus haben, es von Hand zu tun, können Sie oft davon profitieren, privateals private... wenn es kompiliert wird, alles gut.
Dan Rosenstark
@ DanielLarsson: Bezüglich Ihrer Bearbeitungsvorschläge: Beide Kommentare gelten für den foo()Anruf.
Martin R
82
Ich zeichne nur ein Diagramm über privat , dateiprivat , offen und öffentlich
Ich hoffe, es kann Ihnen schnell helfen. Eine Textbeschreibung finden Sie in der Antwort von Martin R.
Achtung, fileprivateist nicht mit der Erweiterung, sondern mit der Datei verknüpft (das Schreiben einer Erweiterung der Klasse A in eine andere Datei erlaubt nicht die Verwendung von fileprivateMitgliedern)
Vince
1
Das scheint falsch. Ihnen fehlt der entscheidende Punkt. Sie müssen zwischen Klassen unterscheiden, die sich innerhalb desselben Moduls befinden und sich in verschiedenen Modulen befinden. Wenn sie sich in verschiedenen Modulen befinden public, können Sie nicht erben, daher ist das dritte Bild falsch. Sie können jeder Klasse auch jederzeit eine Erweiterung hinzufügen, wenn Sie sie sehen können. Es ist daher keine gute Idee, die Sichtbarkeit von Erweiterungen zu erklären.
Sulthan
In der Tat sollte ich erwähnen, dass mein Diagramm nur auf demselben Modul funktioniert. Daher möchte ich, dass das dritte Bild, das der Benutzer schnell verstehen soll, dass Fileprivate nur auf derselben Datei funktioniert.
Stephen Chen
6
Eine praktische Faustregel ist, dass Sie private für Variablen, Konstanten, innere Strukturen und Klassen verwenden, die nur innerhalb der Deklaration Ihrer Klasse / Struktur verwendet werden. Sie verwenden fileprivate für Dinge, die innerhalb Ihrer Erweiterungen innerhalb derselben Datei wie Ihre Klasse / Struktur verwendet werden, jedoch außerhalb ihrer definierenden geschweiften Klammern (dh ihres lexikalischen Bereichs).
classViewController:UIViewController{@IBOutletvar tableView:UITableView!//This is not used outside of class Viewcontroller
privatevar titleText ="Demo"//This gets used in the extension
fileprivatevar list =[String]()overridefunc viewDidLoad(){
navigationItem.title = titleText
}}extensionViewController:UITableViewDataSource{func numberOfSections(in tableView:UITableView)->Int{return list.count
}}
In Swift 4.0 ist Private jetzt in der Erweiterung, jedoch in derselben Datei, verfügbar. Wenn Sie eine Erweiterung in einer anderen Datei deklarieren / definieren, kann Ihre Erweiterung nicht auf Ihre private Variable zugreifen **
File Private File-Private Access beschränkt die Verwendung einer Entität auf ihre eigene definierende Quelldatei. Verwenden Sie den dateiprivaten Zugriff, um die Implementierungsdetails einer bestimmten Funktionalität auszublenden, wenn diese Details in einer gesamten Datei verwendet werden.
Syntax: fileprivate <var type> <variable name> Beispiel:fileprivate class SomeFilePrivateClass {}
Privat Privater Zugriff beschränkt die Verwendung einer Entität auf die beiliegende Deklaration und auf Erweiterungen dieser Deklaration, die sich in derselben Datei befinden . Verwenden Sie den privaten Zugriff, um die Implementierungsdetails einer bestimmten Funktionalität auszublenden, wenn diese Details nur in einer einzelnen Deklaration verwendet werden.
Syntax: private <var type> <variable name> Beispiel:private class SomePrivateClass {}
Schauen Sie sich diese Bilder an: Datei: ViewController.swift Hier befinden sich sowohl die Erweiterung als auch der Ansichtscontroller in derselben Datei, sodass auf private Variablen testPrivateAccessLevelin der Erweiterung zugegriffen werden kann
Datei: TestFile.swift Hier befinden sich sowohl die Erweiterung als auch der Ansichts-Controller in unterschiedlichen Dateien, sodass auf private Variablen testPrivateAccessLevelin der Erweiterung nicht zugegriffen werden kann
.
Hier ist die Klasse ViewController2eine Unterklasse von ViewControllerund beide befinden sich in derselben Datei. Hier ist auf die private Variable testPrivateAccessLevelin der Unterklasse nicht zugegriffen, auf fileprivate jedoch in der Unterklasse.
Obwohl die Antwort von @ MartinR und @ StephenChen perfekt ist, ändert Swift 4 die Dinge ein wenig.
Privat wird jetzt als privat für eine Klasse betrachtet, in der es deklariert ist, sowie für seine Erweiterungen.
FilePrivate wird in dieser Datei als privat betrachtet, sei es eine Klasse, in der die Variable definiert ist, ihre Erweiterung oder eine andere Klasse, die in derselben Datei definiert ist.
Fügen Sie zur besseren Übersichtlichkeit das Code-Snippet in Playground ein
classSum1{let a:Int!let b:Int!privatevar result:Int?fileprivatevar resultt:Int?init(a :Int, b:Int){self.a = a
self.b = b
}func sum(){
result = a + b
print(result as!Int)}}let aObj =Sum1.init(a:10, b:20)
aObj.sum()
aObj.resultt //File Private Accessible as inside same swift file
aObj.result //Private varaible will not be accessible outside its definition except extensions
extensionSum1{func testing(){// Both private and fileprivate accessible in extensions
print(result)
print(resultt)}}//If SUM2 class is created in same file as Sum1 ---
classSum2{func test(){let aSum1=Sum1.init(a:2, b:2)// Only file private accessible
aSum1.resultt
}}
Hinweis : Außerhalb der Swift-Datei kann nicht auf private und dateiprivate Dateien zugegriffen werden.
filePrivate - Die Zugriffssteuerungsebene befindet sich in der Datei.
Fall 1 : Wenn wir eine Erweiterung mit derselben Klassendatei erstellen und versuchen, auf die Dateiprivatfunktion oder die Dateiprivateigenschaft in ihrer Erweiterung zuzugreifen - Zugriff erlaubt Fall 2 : Wenn wir eine Klassenerweiterung in einer neuen Datei erstellen - Und jetzt versuchen, auf die Dateiprivatfunktion oder die Dateiprivatfunktion zuzugreifen Eigentum - Zugang nicht erlaubt
Die private Zugriffskontrollebene ist lexikalisch
Fall 1 : Wenn Eigenschaft oder Funktion in der Klasse als privat deklariert ist, ist der Gültigkeitsbereich standardmäßig die Klasse.
Fall 2 : Wenn eine private Instanz mit im Funktionskörper deklariert ist, ist der Umfang der Instanz auf den Funktionskörper beschränkt.
Dies ist die Erklärung für Swift 4. Für Swift 3 ist der Unterschied der private. Auf swift 3 private kann nicht über seine Erweiterung zugegriffen werden, nur Klasse A selbst kann darauf zugreifen.
Nach Swift 4 wird fileprivate etwas redundant, da die Person normalerweise die Unterklasse nicht in derselben Datei definiert. Privat sollte für die meisten Fälle ausreichen.
private
zufileprivate
. Wenn Sie jedoch den Luxus haben, es von Hand zu tun, können Sie oft davon profitieren,private
alsprivate
... wenn es kompiliert wird, alles gut.foo()
Anruf.Ich zeichne nur ein Diagramm über privat , dateiprivat , offen und öffentlich
Ich hoffe, es kann Ihnen schnell helfen. Eine Textbeschreibung finden Sie in der Antwort von Martin R.
[Update Swift 4]
quelle
fileprivate
ist nicht mit der Erweiterung, sondern mit der Datei verknüpft (das Schreiben einer Erweiterung der Klasse A in eine andere Datei erlaubt nicht die Verwendung vonfileprivate
Mitgliedern)public
, können Sie nicht erben, daher ist das dritte Bild falsch. Sie können jeder Klasse auch jederzeit eine Erweiterung hinzufügen, wenn Sie sie sehen können. Es ist daher keine gute Idee, die Sichtbarkeit von Erweiterungen zu erklären.Eine praktische Faustregel ist, dass Sie private für Variablen, Konstanten, innere Strukturen und Klassen verwenden, die nur innerhalb der Deklaration Ihrer Klasse / Struktur verwendet werden. Sie verwenden fileprivate für Dinge, die innerhalb Ihrer Erweiterungen innerhalb derselben Datei wie Ihre Klasse / Struktur verwendet werden, jedoch außerhalb ihrer definierenden geschweiften Klammern (dh ihres lexikalischen Bereichs).
quelle
In Swift 4.0 ist Private jetzt in der Erweiterung, jedoch in derselben Datei, verfügbar. Wenn Sie eine Erweiterung in einer anderen Datei deklarieren / definieren, kann Ihre Erweiterung nicht auf Ihre private Variable zugreifen **
File Private
File-Private Access beschränkt die Verwendung einer Entität auf ihre eigene definierende Quelldatei. Verwenden Sie den dateiprivaten Zugriff, um die Implementierungsdetails einer bestimmten Funktionalität auszublenden, wenn diese Details in einer gesamten Datei verwendet werden.
Syntax:
fileprivate <var type> <variable name>
Beispiel:
fileprivate class SomeFilePrivateClass {}
Privat
Privater Zugriff beschränkt die Verwendung einer Entität auf die beiliegende Deklaration und auf Erweiterungen dieser Deklaration, die sich in derselben Datei befinden . Verwenden Sie den privaten Zugriff, um die Implementierungsdetails einer bestimmten Funktionalität auszublenden, wenn diese Details nur in einer einzelnen Deklaration verwendet werden.
Syntax:
private <var type> <variable name>
Beispiel:
private class SomePrivateClass {}
Hier finden Sie weitere Details zu allen Zugriffsebenen: Swift - Zugriffsebenen
Schauen Sie sich diese Bilder an:
Datei: ViewController.swift
Hier befinden sich sowohl die Erweiterung als auch der Ansichtscontroller in derselben Datei, sodass auf private Variablen
testPrivateAccessLevel
in der Erweiterung zugegriffen werden kannDatei: TestFile.swift
Hier befinden sich sowohl die Erweiterung als auch der Ansichts-Controller in unterschiedlichen Dateien, sodass auf private Variablen
testPrivateAccessLevel
in der Erweiterung nicht zugegriffen werden kann .Hier ist die Klasse
ViewController2
eine Unterklasse vonViewController
und beide befinden sich in derselben Datei. Hier ist auf die private VariabletestPrivateAccessLevel
in der Unterklasse nicht zugegriffen, auf fileprivate jedoch in der Unterklasse.quelle
Obwohl die Antwort von @ MartinR und @ StephenChen perfekt ist, ändert Swift 4 die Dinge ein wenig.
Privat wird jetzt als privat für eine Klasse betrachtet, in der es deklariert ist, sowie für seine Erweiterungen.
FilePrivate wird in dieser Datei als privat betrachtet, sei es eine Klasse, in der die Variable definiert ist, ihre Erweiterung oder eine andere Klasse, die in derselben Datei definiert ist.
quelle
Aktualisiert für Swift 5
Private vs FilePrivate
Fügen Sie zur besseren Übersichtlichkeit das Code-Snippet in Playground ein
Hinweis : Außerhalb der Swift-Datei kann nicht auf private und dateiprivate Dateien zugegriffen werden.
quelle
filePrivate - Die Zugriffssteuerungsebene befindet sich in der Datei.
Fall 1 : Wenn wir eine Erweiterung mit derselben Klassendatei erstellen und versuchen, auf die Dateiprivatfunktion oder die Dateiprivateigenschaft in ihrer Erweiterung zuzugreifen - Zugriff erlaubt
Fall 2 : Wenn wir eine Klassenerweiterung in einer neuen Datei erstellen - Und jetzt versuchen, auf die Dateiprivatfunktion oder die Dateiprivatfunktion zuzugreifen Eigentum - Zugang nicht erlaubt
Die private Zugriffskontrollebene ist lexikalisch
Fall 1 : Wenn Eigenschaft oder Funktion in der Klasse als privat deklariert ist, ist der Gültigkeitsbereich standardmäßig die Klasse. Fall 2 : Wenn eine private Instanz mit im Funktionskörper deklariert ist, ist der Umfang der Instanz auf den Funktionskörper beschränkt.
quelle
Im folgenden Beispiel werden Sprachkonstrukte geändert
private
undfileprivate
scheinen sich identisch zu verhalten:Das ist nach Intuition, denke ich. Aber gibt es eine Ausnahme?
Herzliche Grüße.
quelle
Dies ist die Erklärung für Swift 4. Für Swift 3 ist der Unterschied der private. Auf swift 3 private kann nicht über seine Erweiterung zugegriffen werden, nur Klasse A selbst kann darauf zugreifen.
Nach Swift 4 wird fileprivate etwas redundant, da die Person normalerweise die Unterklasse nicht in derselben Datei definiert. Privat sollte für die meisten Fälle ausreichen.
quelle
Ich mag das, weil es für Ivare super einfach ist.
Versuchen Sie, fileprivate in private (und umgekehrt) zu ändern, und sehen Sie, was beim Kompilieren passiert ...
quelle