Jaki jest dobry przykład, aby odróżnić fileprivate i private w Swift3

Ten artykuł był pomocny w zrozumieniu nowych specyfikacji dostępu w Swift 3. Podaje również przykłady różnych zastosowań fileprivate i private.

Moje pytanie brzmi - czy użycie fileprivate Na funkcji, która będzie używana tylko w tym pliku nie jest tym samym co użycie private?

Author: Krunal, 2016-08-18

9 answers

fileprivate jest tym, co private było wcześniej Wydania Swift: dostępne z ten sam plik źródłowy. Deklaracja oznaczona jako private może być teraz dostępna tylko w zakresie leksykalnym, w którym jest zadeklarowana. Więc private jest bardziej restrykcyjne 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 źródle plik):

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 private foo jest dostępna tylko w zakresie definicja class A { ... }. Nie jest nawet dostępny z rozszerzenie do typu (w Swift 3, patrz druga uwaga poniżej zmiany w Swift 4).

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

uwagi:

  1. Propozycja SE-0159-Fix Private Access Levels sugerowała powrót do semantyka Swift 2 w języku Swift 4. Po długiej i kontrowersyjnej dyskusji na liście dyskusyjnej swift-evolution, propozycja została odrzucona.

  2. Propozycja SE-0169-poprawa interakcji między prywatnymi deklaracjami i rozszerzeniami sugeruje, aby private deklaracje wewnątrz typu dostępnego dla rozszerzeń tego samego typu jeśli rozszerzenie jest zdefiniowane w tym samym pliku źródłowym. Propozycja ta została przyjęta i wdrożona w Swift 4.

 238
Author: Martin R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-20 20:40:14

Rysuję diagram o prywatnych, fileprivate, open and public

Mam nadzieję, że szybko ci pomoże, opis tekstowy znajduje się w odpowiedzi Martina R

[ Update Swift 4 ]

Tutaj wpisz opis obrazka

 67
Author: Stephen Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 05:00:57

Praktyczna zasada jest taka, że używasz prywatnych dla zmiennych, stałych, wewnętrznych struktur 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(np. 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
        }
    }
 6
Author: Josh Homann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-29 00:40:33

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

Private jest teraz uważane za prywatne dla klasy, w której jest zadeklarowana, a także dla jej rozszerzeń.

FilePrivate jest uważany za prywatny w tym Pliku, czy to klasa, w której zmienna jest zdefiniowana, jej rozszerzenie, czy jakiekolwiek inne klasy zdefiniowane w tym samym pliku.

 4
Author: Nikita P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 08:33:08

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 chyba według intuicji. Ale czy jest jakiś wyjątek? Pozdrawiam serdecznie.
 3
Author: Tomas Balderas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-21 06:20:03

W Swift 4.0, Private jest teraz dostępny w rozszerzeniu, ale w tym samym pliku. Jeśli zadeklarujesz / zdefiniujesz rozszerzenie w innym pliku, wtedy twoja prywatna zmienna nie będzie dostępna dla Twojego rozszerzenia * *

Plik Prywatny
File-private access ogranicza użycie encji do własnego definiującego pliku źródłowego. Użyj file-private access, aby ukryć szczegóły implementacji określonej 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 {}


Private
Private access ogranicza użycie encji do załączającej deklaracji i rozszerzeń tej deklaracji, które znajdują się w tym samym pliku. Użyj dostępu prywatnego, aby ukryć szczegóły implementacji określonej funkcjonalności, gdy dane te 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 wszystkie poziomy dostępu: Swift-poziomy dostępu

spójrz na to zdjęcie:
Plik: ViewController.swift
tutaj rozszerzenie i kontroler widoku znajdują się w tym samym pliku, stąd prywatna zmienna testPrivateAccessLevel jest dostępna w rozszerzeniu

Tutaj wpisz opis obrazka


Plik: TestFile.swift
tutaj rozszerzenie i kontroler widoku znajdują się w różnych plikach, stąd prywatna zmienna testPrivateAccessLevel nie jest dostępna w przedłużenie.

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka


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.

Tutaj wpisz opis obrazka

 2
Author: Krunal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-09 13:54:09
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 dla ivars.

Spróbuj zmienić fileprivate na private (I vice versa) i zobacz co się stanie podczas kompilacji...

 1
Author: CPD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 22:26:04

FilePrivate - poziom kontroli dostępu znajduje się wewnątrz pliku.

Case 1: Jeżeli utworzymy rozszerzenie z plikiem w tej samej klasie i spróbujemy uzyskać dostęp do funkcji fileprivate lub właściwości fileprivate w jej rozszerzeniu-dostęp dozwolony
case 2: Jeżeli utworzymy rozszerzenie klasy w Nowym pliku - a teraz spróbujemy uzyskać dostęp do funkcji fileprivate lub właściwości fileprivate-access not allowed

Private - poziom kontroli dostępu jest z zakresu leksykalnego

Case 1: Jeżeli właściwość lub funkcja jest zadeklarowana jako prywatna w klasie - wtedy scope jest domyślnie klasą. przypadek 2 : jeśli instancja prywatna jest zadeklarowana z ciałem funkcji - wtedy zakres instancji jest ograniczony do ciała funkcji.

 1
Author: Ashish Chhabra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 05:27:59

To jest wyjaśnienie dla swift 4. Dla swift 3 różnica jest prywatna. swift 3 private nie może być dostępny przez jego rozszerzenie, tylko sama Klasa A może uzyskać dostęp.

Tutaj wpisz opis obrazka Po swift 4 fileprivate staje się nieco zbędny, ponieważ osoba normalnie nie zdefiniuje podklasy w tym samym pliku. Prywatne powinno wystarczyć w większości przypadków.

 0
Author: Weidian Huang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-22 04:15:07