Odpowiedzi:
fileprivate
jest teraz tym, co private
było we wcześniejszych wersjach Swift: dostępne z tego samego pliku źródłowego. Deklaracja oznaczona jako private
jest teraz dostępna tylko w zakresie leksykalnym, w którym jest zadeklarowana. Więc private
jest 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 {
private func foo() {}
fileprivate func 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 foo
jest 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 bar
jest 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.
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]
fileprivate
nie jest powiązany z rozszerzeniem, ale z plikiem (zapisanie rozszerzenia klasy A w innym pliku nie pozwoli na użycie fileprivate
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).
class ViewController: UIViewController {
@IBOutlet var tableView: UITableView!
//This is not used outside of class Viewcontroller
private var titleText = "Demo"
//This gets used in the extension
fileprivate var list = [String]()
override func viewDidLoad() {
navigationItem.title = titleText
}
}
extension ViewController: 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 {}
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 rozszerzeniu
Plik: 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 prywatna testPrivateAccessLevel
nie 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.
Zaktualizowano dla Swift 5
Prywatne a FilePrivate
Dla większej przejrzystości wklej fragment kodu w Playground
class Sum1 {
let a: Int!
let b: Int!
private var result: Int?
fileprivate var 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
extension Sum1{
func testing() {
// Both private and fileprivate accessible in extensions
print(result)
print(resultt)
}
}
//If SUM2 class is created in same file as Sum1 ---
class Sum2{
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.
W poniższym przykładzie konstrukcje językowe zmodyfikowane przez private
i fileprivate
wydają się zachowywać identycznie:
fileprivate func fact(_ n: Int) -> Int {
if (n == 0) {
return 1
} else {
return n * fact(n - 1)
}
}
private func gauss(_ n: Int) -> Int {
if (n == 0) {
return 0
} else {
return n + gauss(n - 1)
}
}
print(fact(0))
print(fact(5))
print(fact(3))
print(gauss(10))
print(gauss(9))
Chyba wynika to z intuicji. Ale czy jest jakiś wyjątek?
Z wyrazami szacunku.
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.
class Privacy {
fileprivate(set) var pu:Int {
get {
return self.pr
}
set {
self.pr = newValue
}
}
private var pr:Int = 0
fileprivate var fp:Int = 0
func ex() {
print("\(self.pu) == \(self.pr) and not \(self.fp)")
}
}
extension Privacy {
func ex2() {
self.pu = 5
self.ex()
}
}
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 ...
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.