2016-08-18 16 views

Odpowiedz

212

fileprivate jest teraz co private kiedyś we wcześniejszych wydaniach: Swift dostępnych od tego samego pliku źródłowego. Do deklaracji oznaczonej jako private można teraz uzyskać dostęp tylko w zakresie leksykalnym, w którym została zadeklarowana. Tak więc private jest bardziej restrykcyjna niż fileprivate.

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 (w jednym pliku źródłowego)

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() 
  • prywatny foo metoda jest dostępna tylko w zakresie definicja class A { ... }. Nie jest dostępne nawet od rozszerzenia na typ (w Swift 3, patrz druga uwaga poniżej dla zmian w Swift 4).

  • Metoda pliku prywatna bar jest dostępna z tego samego pliku źródłowego.

Uwagi:

  1. Propozycja SE-0159 – Fix Private Access Levels zasugerował, aby powrócić do Swift 2 semantyki w Swift 4. Po długiej i kontrowersyjnej dyskusji na liście dyskusyjnej Swift-ewolucja, wniosek został rejected.

  2. Propozycja SE-0169 – Improve Interaction Between private Declarations and Extensions sugeruje, aby private deklaracje wewnątrz typu dostępnym na przedłużenie tego samego typu jeśli rozszerzenie jest zdefiniowana w tym samym pliku źródłowego . Ta propozycja została przyjęta i wdrożona w Swift 4.

+2

Jeśli konwertujesz kod automatycznie z Swift 2 na 3, Xcode zamieni 'private' na' fileprivate'. Jeśli jednak masz luksus robienia tego ręcznie, często możesz odnieść korzyść z pozostawienia "prywatnego" jako "prywatnego" ... jeśli to kompiluje, wszystko dobrze. –

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

} 

Lubię to, bo to jest bardzo proste do Ivars.

Spróbuj zmienić fileprivate do prywatnego (i odwrotnie) i zobaczyć, co dzieje się na kompilacji ...

4

Praktyczną zasadą jest używanie prywatnego dla zmiennych, stałych, wewnętrznych strukturach i klas, które są używane tylko wewnątrz deklaracji twojej klasy/struktury. Używasz fileprivate dla 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 zasięg 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 
     } 
    } 
56

po prostu narysować schemat o prywatny, fileprivate, otwieranie, zamykanie

Nadzieję, że może szybko pomóc, do opisu tekstowego można znaleźć odpowiedź Martin R „s

New

Dzięki za odpowiedź Sulthan. Ten schemat działa tylko na tym samym module

enter image description here

+6

uważaj, 'fileprivate' nie jest połączony z rozszerzeniem, ale do pliku (zapisanie rozszerzenia klasy A w innym pliku nie pozwoli na użycie' fileprivate' członków) – Vince

+1

, a także thx @Vince poprawi mój błąd. :) –

+1

Wydaje się to niepoprawne. Brakuje kluczowego punktu. Musisz rozróżnić klasy znajdujące się w tym samym module i znajdujące się w różnych modułach. Jeśli są w różnych modułach, "public" nie pozwoli ci dziedziczyć, dlatego trzeci obraz jest niepoprawny.Zawsze możesz umieścić rozszerzenie na dowolnej klasie, jeśli ją widzisz. Wyjaśnienie widoczności na rozszerzeniach nie jest wtedy dobrym pomysłem. – Sulthan

3

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

to jest zgodnie z intuicją, tak myślę. Ale czy jest jakiś wyjątek?

Z wyrazami szacunku.

3

Chociaż odpowiedzi @ MartinR i @ StephenChen są idealne, Swift 4 zmienia trochę rzeczy.

Prywatny jest teraz uważany za prywatny dla klasy, w której jest zadeklarowany, a także dla rozszerzeń.

FilePrivate jest uważane za prywatne w tym pliku, czy jest to klasa, w której zdefiniowano zmienną, jej rozszerzenie lub inne klasy zdefiniowane w tym samym pliku.

0

W Swift 4.0 opcja Prywatne jest teraz dostępna w rozszerzeniu, ale w tym samym pliku. Jeśli zadeklarujesz/określić rozszerzenie w innym pliku, wówczas zmienna prywatny nie będzie dostępna do rozszerzenia **

Plik Prywatna
dostęp File-prywatnego ogranicza stosowanie jednostki do własnej definiującej pliku źródłowego. Użyj dostępu do pliku prywatnego, aby ukryć szczegóły implementacji określonego elementu funkcjonalności, gdy te szczegóły są używane w całym pliku.
Składnia:fileprivate <var type> <variable name>
Przykład:fileprivate class SomeFilePrivateClass {}


Prywatna
Prywatny dostęp ogranicza stosowanie podmiotu do oświadczenia otaczającej oraz przedłużeń tej deklaracji że są w tym samym plik. Użyj dostępu prywatnego, aby ukryć szczegóły implementacji określonego elementu funkcjonalności, gdy te szczegóły są używane tylko w ramach pojedynczej deklaracji.
Składnia:private <var type> <variable name>
Przykład:private class SomePrivateClass {}


Oto więcej szczegółów na temat wszystkich poziomach dostępu: Swift - Access Levels

Spójrz na to obrazy:
pliku: ViewController.swift
Tutaj oba kontrolki rozszerzenia i widoku są takie same Plik, stąd prywatna zmienna testPrivateAccessLevel dostępny jest w rozszerzeniu

enter image description here


Plik: TestFile.swift
Tutaj rozbudowa i widok kontroler oba są w różnych plików, stąd prywatna zmienna testPrivateAccessLevel nie jest dostępna w rozszerzeniu.

enter image description here

enter image description here


Tutaj klasa ViewController2 jest podklasą ViewController i oba są w tym samym pliku. W tym przypadku zmienna prywatna testPrivateAccessLevel nie jest dostępna w podklasie, ale fileprivate jest dostępny w podklasie.

enter image description here

0

filePrivate - Poziom dostępu Controll jest w pliku.

przypadek 1: Jeśli stworzymy rozszerzenie ze w tym samym pliku klasy i próby uzyskania dostępu do funkcji fileprivate lub mienia fileprivate w jego przedłużenia - dostęp dozwolony
Przypadek 2: Jeśli stworzymy rozszerzenie klasy w nowym pliku - A teraz próbują uzyskać dostęp do funkcji fileprivate lub mienia fileprivate - dostęp niedozwolone

prywatny - poziom kontroli dostępu jest ze w zakresie leksykalnym

case 1: Jeśli własność lub funkcja jest zadeklarowana jako prywatna w klasie - wówczas zasięg jest domyślnie klasą. sprawa 2: jeśli prywatna instancja jest zadeklarowana w ciele funkcji - wówczas zakres instancji jest ograniczony do treści funkcji.

Powiązane problemy