fileprivatejest teraz tym, co privatebyło we wcześniejszych wersjach Swift: dostępne z tego samego pliku źródłowego. Deklaracja oznaczona jako privatejest teraz dostępna tylko w zakresie leksykalnym, w którym jest zadeklarowana. Więc privatejest bardziej restrykcyjna niż fileprivate.
Począwszy od Swift 4, prywatne deklaracje wewnątrz typu są dostępne dla rozszerzeń tego samego typu, jeśli rozszerzenie jest zdefiniowane w tym samym pliku źródłowym.
Przykład (wszystko w jednym pliku źródłowym):
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()
Metoda prywatna foojest dostępna tylko w zakresie class A { ... }definicji. Nie jest nawet dostępny z rozszerzenia do typu (w Swift 3, zobacz drugą uwagę poniżej, aby zapoznać się ze zmianami w Swift 4).
Metoda plik-prywatny barjest dostępna z tego samego pliku źródłowego.
Uwagi:
Propozycja SE-0159 - Fix Private Access Levels sugerowała powrót do semantyki Swift 2 w Swift 4. Po długiej i kontrowersyjnej dyskusji na temat listy mailingowej swift-evolution, propozycja została odrzucona .
Propozycja SE-0169 - Poprawa interakcji między prywatnymi deklaracjami i rozszerzeniami sugeruje, aby private
deklaracje wewnątrz typu były dostępne dla rozszerzeń tego samego typu, jeśli rozszerzenie jest zdefiniowane w tym samym pliku źródłowym.
Ta propozycja została zaakceptowana i wdrożona w Swift 4.
Jeśli automatycznie konwertujesz kod ze Swift 2 na 3, Xcode zmieni się privatew fileprivate. Jeśli jednak masz luksus robienia tego ręcznie, często możesz skorzystać z pozostawienia go privatetak, privatejakby… jeśli się skompiluje, wszystko dobrze.
Dan Rosenstark
@DanielLarsson: Jeśli chodzi o sugestie zmian: oba komentarze odnoszą się do foo()rozmowy.
Martin R
82
Po prostu rysuję diagram dotyczący prywatnego , prywatnego pliku , otwartego i publicznego
Nadzieję, że może szybko pomóc, do opisu tekstowego patrz Martin R odpowiedź „s
uważaj, fileprivatenie jest powiązany z rozszerzeniem, ale z plikiem (zapisanie rozszerzenia klasy A w innym pliku nie pozwoli na użycie fileprivateczłonków)
Vince
1
Wydaje się to niewłaściwe. Brakuje Ci kluczowego punktu. Musisz rozróżnić klasy znajdujące się w tym samym module i w różnych modułach. Jeśli są w różnych modułach public, nie pozwolą Ci na dziedziczenie, dlatego trzeci obraz jest nieprawidłowy. Możesz też zawsze dodać rozszerzenie do dowolnej klasy, jeśli ją widzisz. Wyjaśnienie widoczności rozszerzeń nie jest więc dobrym pomysłem.
Sulthan
Rzeczywiście, powinienem wspomnieć, że mój diagram działa tylko na tym samym module, dlatego trzeci obraz Chcę tylko, aby użytkownik szybko zrozumiał, że fileprivate działa tylko na tym samym pliku.
Stephen Chen
6
Praktyczna zasada jest taka, że używasz private dla zmiennych, stałych, struktur wewnętrznych i klas, które są używane tylko w deklaracji twojej klasy / struktury. Używasz fileprivate do rzeczy, które są używane wewnątrz twoich rozszerzeń w tym samym pliku co twoja klasa / struktura, ale poza ich definiującymi nawiasami klamrowymi (tj. Ich zakres leksykalny).
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
}}
W Swift 4.0 prywatna jest teraz dostępna w rozszerzeniu, ale w tym samym pliku. Jeśli zadeklarujesz / zdefiniujesz rozszerzenie w innym pliku, twoja prywatna zmienna nie będzie dostępna dla twojego rozszerzenia **
Plik prywatny Dostęp prywatny do pliku ogranicza użycie jednostki do jej własnego definiującego pliku źródłowego. Użyj prywatnego dostępu do plików, aby ukryć szczegóły implementacji określonej funkcji, gdy te szczegóły są używane w całym pliku.
Składnia: fileprivate <var type> <variable name> Przykład:fileprivate class SomeFilePrivateClass {}
Prywatny Prywatny dostęp ogranicza użycie jednostki do załączonej deklaracji i do rozszerzeń tej deklaracji, które znajdują się w tym samym pliku . Użyj dostępu prywatnego, aby ukryć szczegóły implementacji określonej funkcji, gdy te szczegóły są używane tylko w ramach jednej deklaracji.
Składnia: private <var type> <variable name> Przykład:private class SomePrivateClass {}
Spójrz na te obrazy: Plik: ViewController.swift
Tutaj rozszerzenie i kontroler widoku znajdują się w tym samym pliku, dlatego zmienna prywatna testPrivateAccessLeveljest dostępna w rozszerzeniu
Plik: TestFile.swift
Tutaj rozszerzenie i kontroler widoku znajdują się w różnych plikach, dlatego zmienna prywatna testPrivateAccessLevelnie jest dostępna w rozszerzeniu.
Tutaj klasa ViewController2jest podklasą ViewControlleri obie znajdują się w tym samym pliku. Tutaj zmienna prywatna testPrivateAccessLevelnie jest dostępna w podklasie, ale fileprivate jest dostępna w podklasie.
Chociaż odpowiedzi @ MartinR i @ StephenChen są doskonałe, Swift 4 trochę zmienia rzeczy.
Prywatny jest teraz traktowany jako prywatny dla klasy, w której jest zadeklarowany, a także dla jego rozszerzeń.
FilePrivate jest uważane za prywatne w tym pliku, niezależnie od tego, czy jest to klasa, w której jest zdefiniowana zmienna, jej rozszerzenie, czy inne klasy zdefiniowane w tym samym pliku.
Dla większej przejrzystości wklej fragment kodu w Playground
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
}}
Uwaga : Poza plikiem Swift zarówno private, jak i fileprivate nie są dostępne.
filePrivate - poziom kontroli dostępu znajduje się w pliku.
Przypadek 1 : Jeśli tworzymy rozszerzenie z w tym samym pliku klasy i spróbujemy uzyskać dostęp do funkcji fileprivate lub właściwości fileprivate w swoim rozszerzeniu - dostęp dozwolony Przypadek 2 : Jeśli utworzymy rozszerzenie klasy w nowym pliku - A teraz spróbuj uzyskać dostęp do funkcji fileprivate lub fileprivate właściwość - dostęp niedozwolony
prywatny - poziom kontroli dostępu jest w zakresie leksykalnym
Przypadek 1 : Jeśli właściwość lub funkcja jest zadeklarowana jako prywatna w klasie - wtedy zasięg jest domyślnie klasą.
przypadek 2 : jeśli prywatna instancja jest zadeklarowana z treścią funkcji - wtedy zakres instancji jest ograniczony do treści funkcji.
To jest wyjaśnienie dla swift 4. W przypadku swift 3 różnica jest prywatna. Swift 3 private nie jest dostępny przez jego rozszerzenie, tylko sama klasa A może uzyskać dostęp.
Po Swift 4 fileprivate staje się trochę zbędne, ponieważ osoba normalnie nie definiuje podklasy w tym samym pliku. Prywatny powinien wystarczyć w większości przypadków.
private
wfileprivate
. Jeśli jednak masz luksus robienia tego ręcznie, często możesz skorzystać z pozostawienia goprivate
tak,private
jakby… jeśli się skompiluje, wszystko dobrze.foo()
rozmowy.Po prostu rysuję diagram dotyczący prywatnego , prywatnego pliku , otwartego i publicznego
Nadzieję, że może szybko pomóc, do opisu tekstowego patrz Martin R odpowiedź „s
[Zaktualizuj Swift 4]
źródło
fileprivate
nie jest powiązany z rozszerzeniem, ale z plikiem (zapisanie rozszerzenia klasy A w innym pliku nie pozwoli na użyciefileprivate
członków)public
, nie pozwolą Ci na dziedziczenie, dlatego trzeci obraz jest nieprawidłowy. Możesz też zawsze dodać rozszerzenie do dowolnej klasy, jeśli ją widzisz. Wyjaśnienie widoczności rozszerzeń nie jest więc dobrym pomysłem.Praktyczna zasada jest taka, że używasz private dla zmiennych, stałych, struktur wewnętrznych i klas, które są używane tylko w deklaracji twojej klasy / struktury. Używasz fileprivate do rzeczy, które są używane wewnątrz twoich rozszerzeń w tym samym pliku co twoja klasa / struktura, ale poza ich definiującymi nawiasami klamrowymi (tj. Ich zakres leksykalny).
źródło
W Swift 4.0 prywatna jest teraz dostępna w rozszerzeniu, ale w tym samym pliku. Jeśli zadeklarujesz / zdefiniujesz rozszerzenie w innym pliku, twoja prywatna zmienna nie będzie dostępna dla twojego rozszerzenia **
Plik
prywatny Dostęp prywatny do pliku ogranicza użycie jednostki do jej własnego definiującego pliku źródłowego. Użyj prywatnego dostępu do plików, aby ukryć szczegóły implementacji określonej funkcji, gdy te szczegóły są używane w całym pliku.
Składnia:
fileprivate <var type> <variable name>
Przykład:
fileprivate class SomeFilePrivateClass {}
Prywatny
Prywatny dostęp ogranicza użycie jednostki do załączonej deklaracji i do rozszerzeń tej deklaracji, które znajdują się w tym samym pliku . Użyj dostępu prywatnego, aby ukryć szczegóły implementacji określonej funkcji, gdy te szczegóły są używane tylko w ramach jednej deklaracji.
Składnia:
private <var type> <variable name>
Przykład:
private class SomePrivateClass {}
Oto więcej szczegółów na temat wszystkich poziomów dostępu: Swift - poziomy dostępu
Spójrz na te obrazy:
Plik: ViewController.swift
Tutaj rozszerzenie i kontroler widoku znajdują się w tym samym pliku, dlatego zmienna prywatna
testPrivateAccessLevel
jest dostępna w rozszerzeniuPlik: TestFile.swift
Tutaj rozszerzenie i kontroler widoku znajdują się w różnych plikach, dlatego zmienna prywatna
testPrivateAccessLevel
nie jest dostępna w rozszerzeniu.Tutaj klasa
ViewController2
jest podklasąViewController
i obie znajdują się w tym samym pliku. Tutaj zmienna prywatnatestPrivateAccessLevel
nie jest dostępna w podklasie, ale fileprivate jest dostępna w podklasie.źródło
Chociaż odpowiedzi @ MartinR i @ StephenChen są doskonałe, Swift 4 trochę zmienia rzeczy.
Prywatny jest teraz traktowany jako prywatny dla klasy, w której jest zadeklarowany, a także dla jego rozszerzeń.
FilePrivate jest uważane za prywatne w tym pliku, niezależnie od tego, czy jest to klasa, w której jest zdefiniowana zmienna, jej rozszerzenie, czy inne klasy zdefiniowane w tym samym pliku.
źródło
Zaktualizowano dla Swift 5
Prywatne a FilePrivate
Dla większej przejrzystości wklej fragment kodu w Playground
Uwaga : Poza plikiem Swift zarówno private, jak i fileprivate nie są dostępne.
źródło
filePrivate - poziom kontroli dostępu znajduje się w pliku.
Przypadek 1 : Jeśli tworzymy rozszerzenie z w tym samym pliku klasy i spróbujemy uzyskać dostęp do funkcji fileprivate lub właściwości fileprivate w swoim rozszerzeniu - dostęp dozwolony
Przypadek 2 : Jeśli utworzymy rozszerzenie klasy w nowym pliku - A teraz spróbuj uzyskać dostęp do funkcji fileprivate lub fileprivate właściwość - dostęp niedozwolony
prywatny - poziom kontroli dostępu jest w zakresie leksykalnym
Przypadek 1 : Jeśli właściwość lub funkcja jest zadeklarowana jako prywatna w klasie - wtedy zasięg jest domyślnie klasą. przypadek 2 : jeśli prywatna instancja jest zadeklarowana z treścią funkcji - wtedy zakres instancji jest ograniczony do treści funkcji.
źródło
W poniższym przykładzie konstrukcje językowe zmodyfikowane przez
private
ifileprivate
wydają się zachowywać identycznie:Chyba wynika to z intuicji. Ale czy jest jakiś wyjątek?
Z wyrazami szacunku.
źródło
To jest wyjaśnienie dla swift 4. W przypadku swift 3 różnica jest prywatna. Swift 3 private nie jest dostępny przez jego rozszerzenie, tylko sama klasa A może uzyskać dostęp.
Po Swift 4 fileprivate staje się trochę zbędne, ponieważ osoba normalnie nie definiuje podklasy w tym samym pliku. Prywatny powinien wystarczyć w większości przypadków.
źródło
Podoba mi się to, ponieważ jest to bardzo proste w przypadku bluszczu.
Spróbuj zmienić fileprivate na private (i odwrotnie) i zobacz, co się stanie podczas kompilacji ...
źródło