Quel est un bon exemple pour différencier fichier privé et privé dans Swift3

142

Cet article a été utile pour comprendre les nouveaux spécificateurs d'accès dans Swift 3. Il donne également quelques exemples de différentes utilisations de fileprivateet private.

Ma question est la suivante: l'utilisation fileprivated'une fonction qui ne sera utilisée que dans ce fichier n'est-elle pas la même que l'utilisation private?

Nikita P
la source

Réponses:

282

fileprivateest maintenant ce privatequi était dans les versions précédentes de Swift: accessible à partir du même fichier source. Une déclaration marquée comme privaten'est désormais accessible que dans la portée lexicale dans laquelle elle est déclarée. C'est donc privateplus restrictif que fileprivate.

Depuis Swift 4, les déclarations privées à l'intérieur d'un type sont accessibles aux extensions du même type si l'extension est définie dans le même fichier source.

Exemple (le tout dans un seul fichier source):

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()
  • Le privé foo méthode n'est accessible que dans le cadre de la class A { ... }définition. Il n'est même pas accessible depuis une extension du type (dans Swift 3, voir la deuxième note ci-dessous pour les changements dans Swift 4).

  • Le fichier privé bar méthode de est accessible à partir du même fichier source.

Remarques:

  1. La proposition SE-0159 - Fixer les niveaux d'accès privé suggérait de revenir à la sémantique de Swift 2 dans Swift 4. Après une discussion longue et controversée sur la liste de diffusion Swift-evolution, la proposition était rejetée .

  2. La proposition SE-0169 - Améliorer l'interaction entre les déclarations privées et les extensions suggère de rendre les private déclarations à l'intérieur d'un type accessibles aux extensions du même type si l'extension est définie dans le même fichier source. Cette proposition a été acceptée et mise en œuvre dans Swift 4.

Martin R
la source
2
Si vous convertissez automatiquement le code de Swift 2 en 3, Xcode se transformera privateen fileprivate. Cependant, si vous avez le luxe de le faire à la main, vous pouvez souvent profiter de partir privatecomme private... si ça compile, tout va bien.
Dan Rosenstark
@DanielLarsson: Concernant vos suggestions de modification: les deux commentaires s'appliquent à l' foo()appel.
Martin R
82

Je viens de dessiner un diagramme sur privé , fichier privé , ouvert et public

J'espère que cela pourra vous aider rapidement, pour la description du texte, veuillez vous référer à la réponse de Martin R.

[Mettre à jour Swift 4]

entrez la description de l'image ici

Stephen Chen
la source
9
attention, fileprivaten'est pas lié à l'extension mais au fichier (écrire une extension de classe A dans un autre fichier ne permettra pas l'utilisation de fileprivatemembres)
Vince
1
Cela semble incorrect. Vous manquez le point clé. Vous devez faire la différence entre les classes qui sont à l'intérieur du même module et qui sont dans des modules différents. S'ils sont dans des modules différents, publiccela ne vous permettra pas d'hériter, donc la 3ème image est incorrecte. De plus, vous pouvez toujours ajouter une extension à n'importe quelle classe si vous pouvez la voir. Expliquer la visibilité sur les extensions n'est donc pas une très bonne idée.
Sulthan
En effet, je dois mentionner que mon schéma ne fonctionne que sur le même module, donc la 3ème image je veux juste que l'utilisateur comprenne rapidement fileprivate ne fonctionne que sur le même fichier.
Stephen Chen
6

Une règle pratique est que vous utilisez private pour les variables, les constantes, les structures internes et les classes qui ne sont utilisées que dans la déclaration de votre classe / structure. Vous utilisez fileprivate pour les choses qui sont utilisées à l'intérieur de vos extensions dans le même fichier que votre classe / structure mais en dehors de leurs accolades définissant (ie. Leur portée lexicale).

    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
        }
    }
Josh Homann
la source
6

Dans Swift 4.0, Private est désormais accessible en extension mais dans le même fichier. Si vous déclarez / définissez une extension dans un autre fichier, votre variable privée ne sera pas accessible à votre extension **

L'
accès au fichier privé au fichier privé limite l'utilisation d'une entité à son propre fichier source de définition. Utilisez l'accès privé de fichier pour masquer les détails d'implémentation d'une fonctionnalité spécifique lorsque ces détails sont utilisés dans un fichier entier.
Syntaxe: fileprivate <var type> <variable name>
Exemple: fileprivate class SomeFilePrivateClass {}


Privé
L'accès privé limite l'utilisation d'une entité à la déclaration englobante et aux extensions de cette déclaration qui se trouvent dans le même fichier . Utilisez l'accès privé pour masquer les détails d'implémentation d'une fonctionnalité spécifique lorsque ces détails ne sont utilisés que dans une seule déclaration.
Syntaxe: private <var type> <variable name>
Exemple: private class SomePrivateClass {}


Voici plus de détails sur tous les niveaux d'accès: Swift - Niveaux d'accès

Regardez ces images:
File: ViewController.swift
Ici l'extension et le contrôleur de vue sont tous deux dans le même fichier, donc la variable privée testPrivateAccessLevelest accessible en extension

entrez la description de l'image ici


File: TestFile.swift
Ici, l'extension et le contrôleur de vue sont tous deux dans des fichiers différents, donc la variable privée testPrivateAccessLeveln'est pas accessible en extension.

entrez la description de l'image ici

entrez la description de l'image ici


Ici, la classe ViewController2est une sous-classe de ViewControlleret les deux sont dans le même fichier. Ici, la variable privée testPrivateAccessLeveln'est pas accessible dans la sous-classe mais fileprivate est accessible dans la sous-classe.

entrez la description de l'image ici

Krunal
la source
5

Bien que les réponses de @ MartinR et @ StephenChen soient parfaites, Swift 4 change un peu les choses.

Privé est désormais considéré comme privé pour une classe dans laquelle il est déclaré ainsi que pour ses extensions.

FilePrivate est considéré comme privé dans ce fichier, qu'il s'agisse d'une classe dans laquelle la variable est définie, de son extension ou de toute autre classe définie dans ce même fichier.

Nikita P
la source
5

Mis à jour pour Swift 5

Privé vs FilePrivate

Pour plus de clarté, collez l'extrait de code dans 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

    }
}

Remarque : en dehors du fichier Swift, les fichiers private et fileprivate ne sont pas accessibles.

Arpit Jain
la source
4

filePrivate - le niveau de contrôle d'accès se trouve dans le fichier.

cas 1 : Si nous créons une extension avec dans le même fichier de classe et essayons d'accéder à la fonction fileprivate ou à la propriété fileprivate dans son extension - accès autorisé
cas 2 : Si nous créons une extension de classe dans un nouveau fichier - Et maintenant essayons d'accéder à la fonction fileprivate ou fileprivate propriété - accès non autorisé

privé - le niveau de contrôle d'accès est à portée lexicale

cas 1 : Si la propriété ou la fonction est déclarée comme privée dans la classe, la portée est par défaut la classe. cas 2 : si une instance privée est déclarée avec dans le corps de la fonction - alors la portée de l'instance est limitée au corps de la fonction.

Ashish Chhabra
la source
3

Dans l'exemple suivant, les constructions de langage modifiées par privateet fileprivatesemblent se comporter de la même manière:

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

C'est selon l'intuition, je suppose. Mais y a-t-il une exception?

Meilleures salutations.

Tomas Balderas
la source
3

C'est l'explication de swift 4. Pour swift 3, la différence est le privé. swift 3 private n'est pas accessible par son extension, seule la classe A elle-même peut y accéder.

entrez la description de l'image ici Après swift 4, fileprivate devient un peu redondant, car normalement personne ne définira la sous-classe dans le même fichier. Privé devrait suffire dans la plupart des cas.

Weidian Huang
la source
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()
    }

}

J'aime ça parce que c'est super simple pour les ivars.

Essayez de changer fileprivate en private (et vice versa) et voyez ce qui se passe lors de la compilation ...

CPD
la source