Qual è un buon esempio per distinguere tra fileprivate e private in Swift3


142

Questo articolo è stato utile per comprendere i nuovi identificatori di accesso in Swift 3. Fornisce anche alcuni esempi di diversi usi di fileprivatee private.

La mia domanda è: non sta usando fileprivateuna funzione che verrà usata solo in questo file come se fosse usando private?

Risposte:


282

fileprivateè ora quello che privateera nelle versioni precedenti di Swift: accessibile dallo stesso file sorgente. Una dichiarazione contrassegnata come privateora è accessibile solo all'interno dell'ambito lessicale in cui è dichiarata. Quindi privateè più restrittiva di fileprivate.

A partire da Swift 4, le dichiarazioni private all'interno di un tipo sono accessibili alle estensioni dello stesso tipo se l'estensione è definita nello stesso file di origine.

Esempio (tutto in un file sorgente):

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()
  • Il foometodo privato è accessibile solo nell'ambito della class A { ... }definizione. Non è nemmeno accessibile da un'estensione al tipo (in Swift 3, vedere la seconda nota in basso per le modifiche in Swift 4).

  • Il barmetodo file-private è accessibile dallo stesso file di origine.

Appunti:

  1. La proposta SE-0159 - Correzione dei livelli di accesso privato ha suggerito di tornare alla semantica di Swift 2 in Swift 4. Dopo una lunga e controversa discussione sulla mailing list di rapida evoluzione, la proposta è stata respinta .

  2. La proposta SE-0169 - Migliorare l'interazione tra dichiarazioni ed estensioni private suggerisce di rendere le private dichiarazioni all'interno di un tipo accessibili alle estensioni dello stesso tipo se l'estensione è definita nello stesso file di origine. Questa proposta è stata accettata e implementata in Swift 4.


2
Se stai convertendo automaticamente il codice da Swift 2 a 3, Xcode si trasformerà privatein fileprivate. Tuttavia, se hai il lusso di farlo a mano, puoi spesso trarre vantaggio dal lasciare privatecome private... se si compila, tutto bene.
Dan Rosenstark,

@DanielLarsson: i tuoi suggerimenti di modifica: entrambi i commenti si applicano alla foo()chiamata.
Martin R,

82

Traccio solo un diagramma su privato , fileprivate , aperto e pubblico

Spero che ti possa aiutare rapidamente, per la descrizione del testo fai riferimento alla risposta di Martin R.

[Aggiorna Swift 4]

inserisci qui la descrizione dell'immagine


9
attenzione, fileprivatenon è collegato all'estensione ma al file (scrivere un'estensione della classe A in un altro file non consentirà l'uso dei fileprivatemembri)
Vince

1
Questo sembra errato. Ti manca il punto chiave. Devi distinguere tra le classi che si trovano all'interno dello stesso modulo e che si trovano in moduli diversi. Se sono in moduli diversi public, non ti permetteranno di ereditare, quindi la terza immagine non è corretta. Inoltre, puoi sempre inserire un'estensione per qualsiasi classe se puoi vederla. Spiegare la visibilità sulle estensioni non è quindi una buona idea.
Sulthan,

In effetti, dovrei menzionare che il mio diagramma funziona solo sullo stesso modulo, quindi la terza immagine voglio solo che l'utente capisca rapidamente che fileprivate funziona solo sullo stesso file.
Stephen Chen,

6

Una pratica regola pratica è che usi private per variabili, costanti, strutture interne e classi che vengono utilizzate solo all'interno della dichiarazione della tua classe / struttura. Usi fileprivate per cose che sono usate all'interno delle tue estensioni all'interno dello stesso file della tua classe / struttura ma al di fuori delle loro parentesi graffe definitive (cioè il loro ambito lessicale).

    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

In Swift 4.0, Private è ora accessibile in estensione ma all'interno dello stesso file. Se dichiari / definisci l'estensione in un altro file, la tua variabile privata non sarà accessibile alla tua estensione **

File
privato L'accesso al file privato limita l'uso di un'entità al proprio file sorgente di definizione. Utilizzare l'accesso privato al file per nascondere i dettagli di implementazione di una specifica funzionalità quando tali dettagli vengono utilizzati all'interno di un intero file.
Sintassi: fileprivate <var type> <variable name>
Esempio: fileprivate class SomeFilePrivateClass {}


Privato
L'accesso privato limita l'uso di un'entità alla dichiarazione allegata e alle estensioni di quella dichiarazione che si trovano nello stesso file . Utilizzare l'accesso privato per nascondere i dettagli di implementazione di una specifica funzionalità quando tali dettagli vengono utilizzati solo all'interno di una singola dichiarazione.
Sintassi: private <var type> <variable name>
Esempio: private class SomePrivateClass {}


Ecco maggiori dettagli su tutti i livelli di accesso: Swift - Livelli di accesso

Guarda queste immagini:
File: ViewController.swift
Qui l'estensione e il controller di visualizzazione sono entrambi nello stesso file, quindi la variabile privata testPrivateAccessLevelè accessibile nell'estensione

inserisci qui la descrizione dell'immagine


File: TestFile.swift
Qui l'estensione e il controller di visualizzazione sono entrambi in file diversi, quindi la variabile privata testPrivateAccessLevelnon è accessibile in estensione.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Qui la classe ViewController2è una sottoclasse di ViewControllered entrambi sono nello stesso file. Qui la variabile privata testPrivateAccessLevelnon è accessibile nella sottoclasse ma fileprivate è accessibile nella sottoclasse.

inserisci qui la descrizione dell'immagine


5

Sebbene la risposta di @ MartinR e @ StephenChen siano perfette, Swift 4 cambia un po 'le cose.

Privato è ora considerato privato per una classe in cui è dichiarato e anche per le sue estensioni.

FilePrivate è considerato privato in quel file, sia esso una classe in cui è definita la variabile, la sua estensione o qualsiasi altra classe definita in quello stesso file.


5

Aggiornato per Swift 5

Privato vs FilePrivate

Per maggiore chiarezza incollare lo snippet di codice in 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

    }
}

Nota : al di fuori del file Swift sia privati ​​che fileprivate non sono accessibili.


4

filePrivate : il livello di controllo dell'accesso è all'interno del file.

caso 1 : se creiamo l'estensione con lo stesso file di classe e proviamo ad accedere alla funzione fileprivate o alla proprietà fileprivate nella sua estensione - accediamo al
caso consentito 2 : se creiamo un'estensione della classe in un nuovo file - E ora proviamo ad accedere alla funzione fileprivate o fileprivate proprietà - accesso non consentito

privato - il livello di controllo degli accessi ha un ambito lessicale

caso 1 : se la proprietà o la funzione è dichiarata come privata nella classe, l'ambito è per impostazione predefinita la classe. caso 2 : se l'istanza privata è dichiarata con nel corpo della funzione, allora l'ambito dell'istanza è limitato al corpo della funzione.


3

Nell'esempio seguente, i costrutti del linguaggio modificati privatee fileprivatesembrano comportarsi in modo identico:

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

Questo è secondo l'intuizione, immagino. Ma c'è qualche eccezione?

Cordiali saluti.


3

Questa è la spiegazione per swift 4. Per swift 3, la differenza è il privato. swift 3 private non è accessibile dalla sua estensione, solo la classe A stessa può accedere.

inserisci qui la descrizione dell'immagine Dopo swift 4, fileprivate diventa un po 'ridondante, poiché normalmente la persona non definisce la sottoclasse nello stesso file. Privato dovrebbe essere sufficiente per la maggior parte dei casi.


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

}

Mi piace perché è super semplice per gli avari.

Prova a cambiare fileprivate in privato (e viceversa) e guarda cosa succede durante la compilazione ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.