Apa contoh yang baik untuk membedakan antara fileprivate dan pribadi di Swift3

142

Ini artikel telah membantu dalam memahami specifiers akses baru di Swift 3. Ini juga memberikan beberapa contoh penggunaan fileprivatedan private.

Pertanyaan saya adalah - tidakkah menggunakan fileprivatefungsi yang hanya akan digunakan dalam file ini sama dengan menggunakan private?

Nikita P
sumber

Jawaban:

282

fileprivatesekarang menjadi apa yang privateada di rilis Swift sebelumnya: dapat diakses dari file sumber yang sama. Deklarasi yang ditandai sebagai privatesekarang hanya dapat diakses dalam lingkup leksikal yang dideklarasikan. Jadi privatelebih membatasi daripada fileprivate.

Pada Swift 4, deklarasi pribadi di dalam suatu tipe dapat diakses oleh ekstensi dari tipe yang sama jika ekstensi didefinisikan dalam file sumber yang sama.

Contoh (semua dalam satu file sumber):

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()
  • fooMetode pribadi hanya dapat diakses dalam ruang lingkup class A { ... }definisi. Ia bahkan tidak dapat diakses dari ekstensi ke tipe (dalam Swift 3, lihat catatan kedua di bawah ini untuk perubahan dalam Swift 4).

  • Metode file-pribadi bardapat diakses dari file sumber yang sama.

Catatan:

  1. Proposal SE-0159 - Memperbaiki Level Akses Pribadi menyarankan untuk kembali ke semantik Swift 2 di Swift 4. Setelah diskusi panjang dan kontroversial pada milis swift-evolusi, proposal tersebut ditolak .

  2. Proposal SE-0169 - Tingkatkan Interaksi Antara Deklarasi dan Ekstensi pribadi menyarankan agar private deklarasi di dalam suatu tipe dapat diakses oleh ekstensi dari tipe yang sama jika ekstensi didefinisikan dalam file sumber yang sama. Proposal ini diterima dan diterapkan di Swift 4.

Martin R
sumber
2
Jika Anda mengonversi kode secara otomatis dari Swift 2 ke 3, Xcode akan berubah privatemenjadi fileprivate. Namun, jika Anda memiliki kemewahan melakukannya dengan tangan, Anda sering dapat mengambil manfaat dari meninggalkan privatesebagai private... jika itu dikompilasi, semuanya baik.
Dan Rosenstark
@DanielLarsson: Re saran sunting Anda: Kedua komentar berlaku untuk foo()panggilan.
Martin R
82

Saya hanya menggambar diagram tentang pribadi , fileprivate , terbuka , dan publik

Semoga ini dapat dengan cepat membantu Anda, untuk deskripsi teks, silakan merujuk ke jawaban Martin R

[Perbarui Swift 4]

masukkan deskripsi gambar di sini

Stephen Chen
sumber
9
hati-hati, fileprivatetidak tertaut ke ekstensi tetapi ke file (menulis ekstensi kelas A di file lain tidak akan mengizinkan penggunaan fileprivateanggota)
Vince
1
Ini sepertinya salah. Anda kehilangan poin kuncinya. Anda harus membedakan antara kelas yang ada di dalam modul yang sama dan yang ada di modul yang berbeda. Jika mereka berada di modul yang berbeda maka publictidak akan memungkinkan Anda untuk mewarisi, oleh karena itu gambar ke-3 salah. Selain itu, Anda selalu dapat menambahkan ekstensi ke kelas apa pun jika Anda bisa melihatnya. Menjelaskan visibilitas pada ekstensi bukanlah ide yang sangat bagus.
Sulthan
Memang, saya harus menyebutkan diagram saya hanya berfungsi pada modul yang sama, oleh karena itu gambar ke-3 saya hanya ingin pengguna dengan cepat memahami fileprivate hanya bekerja pada file yang sama.
Stephen Chen
6

Aturan praktis praktis adalah bahwa Anda menggunakan privat untuk variabel, konstanta, struct dalam dan kelas yang hanya digunakan di dalam deklarasi kelas / struct Anda. Anda menggunakan fileprivate untuk hal-hal yang digunakan di dalam ekstensi Anda dalam file yang sama dengan kelas / struct Anda tetapi di luar dari kurung kurawal yang menentukan (mis. Ruang leksikal mereka).

    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
sumber
6

Di Swift 4.0, Private sekarang dapat diakses dalam ekstensi tetapi dalam file yang sama. Jika Anda mendeklarasikan / menetapkan ekstensi dalam file lain, maka variabel pribadi Anda tidak akan dapat diakses oleh ekstensi Anda **

File Privat
File akses privat membatasi penggunaan entitas untuk file sumber pendefinisiannya sendiri. Gunakan akses file-pribadi untuk menyembunyikan detail implementasi dari bagian fungsionalitas tertentu ketika detail tersebut digunakan dalam seluruh file.
Sintaks: fileprivate <var type> <variable name>
Contoh: fileprivate class SomeFilePrivateClass {}


Pribadi
Akses pribadi membatasi penggunaan suatu entitas pada deklarasi terlampir, dan pada ekstensi deklarasi yang berada dalam file yang sama . Gunakan akses pribadi untuk menyembunyikan detail implementasi dari bagian fungsionalitas tertentu ketika detail tersebut hanya digunakan dalam satu deklarasi.
Sintaks: private <var type> <variable name>
Contoh: private class SomePrivateClass {}


Berikut ini lebih detail tentang semua level akses: Swift - Level Akses

Lihat gambar ini:
File: ViewController.swift
Di sini, ekstensi dan pengontrol tampilan keduanya dalam file yang sama, maka variabel pribadi testPrivateAccessLeveldapat diakses dalam ekstensi

masukkan deskripsi gambar di sini


File: TestFile.swift
Di sini ekstensi dan pengontrol tampilan keduanya dalam file yang berbeda, maka variabel pribadi testPrivateAccessLeveltidak dapat diakses dalam ekstensi.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini


Kelas di sini ViewController2adalah subkelas ViewControllerdan keduanya berada dalam file yang sama. Di sini variabel pribadi testPrivateAccessLeveltidak dapat diakses di Subclass tetapi fileprivate dapat diakses di subclass.

masukkan deskripsi gambar di sini

Krunal
sumber
5

Meskipun jawaban @ MartinR dan @ StephenChen sempurna, Swift 4 mengubah sedikit hal.

Privat sekarang dianggap sebagai privat untuk kelas di mana ia dinyatakan dan juga untuk ekstensi.

FilePrivate dianggap pribadi dalam file itu baik itu kelas di mana variabel didefinisikan, itu ekstensi, atau kelas lain yang didefinisikan dalam file yang sama.

Nikita P
sumber
5

Diperbarui untuk Swift 5

Pribadi vs FilePrivate

Untuk lebih jelasnya tempelkan cuplikan kode di 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

    }
}

Catatan : Di luar file Swift, baik privat dan fileprivate tidak dapat diakses.

Arpit Jain
sumber
4

filePrivate - level kontrol akses ada di dalam file.

kasus 1 : Jika kita membuat ekstensi dengan file kelas yang sama dan mencoba mengakses fungsi fileprivate atau properti fileprivate dalam ekstensinya - akses yang diizinkan
kasus 2 : Jika kita membuat ekstensi kelas di file baru - Dan sekarang coba akses fungsi fileprivate atau fileprivate properti - akses tidak diizinkan

pribadi - tingkat kontrol akses dengan dalam lingkup leksikal

kasus 1 : Jika properti atau fungsi dinyatakan sebagai pribadi di kelas - maka ruang lingkup secara default adalah kelas. kasus 2 : jika instance pribadi dideklarasikan dengan di fungsi tubuh - maka cakupan instance terbatas pada fungsi fungsi.

Ashish Chhabra
sumber
3

Dalam contoh berikut, konstruksi bahasa dimodifikasi oleh privatedan fileprivatetampaknya berperilaku identik:

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

Ini menurut intuisi, kurasa. Tapi, adakah pengecualian?

Salam hormat.

Tomas Balderas
sumber
3

Ini adalah penjelasan untuk swift 4. Untuk swift 3, perbedaannya adalah pribadi. Swift 3 pribadi tidak dapat diakses oleh ekstensi, hanya Kelas A itu sendiri dapat mengakses.

masukkan deskripsi gambar di sini Setelah cepat 4, fileprivate menjadi sedikit berlebihan, karena orang biasanya tidak akan mendefinisikan subkelas dalam file yang sama. Pribadi harus cukup untuk sebagian besar kasus.

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

}

Saya suka ini karena sangat sederhana untuk ivars.

Coba ubah fileprivate menjadi pribadi (dan sebaliknya) dan lihat apa yang terjadi pada kompilasi ...

CPD
sumber