Swift3'te fileprivate ve private arasında ayrım yapmak için iyi bir örnek nedir


142

Bu makale , içindeki yeni erişim belirteçlerini anlamada yardımcı olmuştur Swift 3. Ayrıca fileprivateve öğelerinin farklı kullanımlarına bazı örnekler verir private.

Benim sorum - fileprivatesadece bu dosyada kullanılacak bir işlevi kullanarak kullanmak değil privatemi?

Yanıtlar:


282

fileprivateşimdi privatedaha önceki Swift sürümlerinde olan şeydi : aynı kaynak dosyadan erişilebilir. privateArtık olarak bildirildiği bildirime yalnızca bildirildiği sözcük kapsamı içinde erişilebilir. Öyleyse privatebundan daha kısıtlayıcıdır fileprivate.

İtibariyle Swift 4, uzatma aynı kaynak dosyada tanımlanması durumunda bir tip iç özel beyanlar aynı tipte uzantıları erişilebilir.

Örnek (hepsi bir kaynak dosyada):

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()
  • Özel fooyönteme yalnızca class A { ... }tanım kapsamında erişilebilir . Türün bir uzantısından bile erişilemez (Swift 3'te, Swift 4'teki değişiklikler için aşağıdaki ikinci nota bakın).

  • Dosya-özel baryöntemine aynı kaynak dosyadan erişilebilir.

Notlar:

  1. Öneri SE-0159 - Fix Özel Erişim Düzeyleri hızlı evrim posta listesindeki uzun ve tartışmalı tartışmalar sonrasında Swift 4'te Swift 2 semantik dönmek önerdi, öneri edildi reddedildi .

  2. SE-0169 önerisi - Özel Bildirimler ve Uzantılar Arasındaki Etkileşimi Geliştirin Uzantı aynı kaynak dosyadaprivate tanımlanmışsa, bir tür içindeki bildirimlerin aynı türdeki uzantılar tarafından erişilebilir olmasını önerir . Bu teklif Swift 4'te kabul edildi ve uygulandı.


2
Kodu otomatik olarak Swift 2'den 3'e dönüştürüyorsanız, Xcode privatedönüşecektir fileprivate. Elle yapıyor lüks varsa Ancak, çoğu zaman terk yararlanabilir privateolarak private... derler bile tüm iyi.
Dan Rosenstark

@DanielLarsson: Düzenleme önerilerinizi tekrarlayın: Her iki yorum da foo()çağrı için geçerlidir .
Martin R

82

Sadece özel , fileprivate , open ve public hakkında bir diyagram çiziyorum

Umarım hızlı bir şekilde size yardımcı olabilir, metin açıklaması için lütfen Martin R'nin cevabına bakın.

[Swift 4'ü Güncelle]

resim açıklamasını buraya girin


9
dikkat fileprivate, uzantıya bağlı değil, dosyaya bağlı (başka bir dosyaya A sınıfı bir uzantı yazmak fileprivateüyelerin kullanımına izin vermez )
Vince

1
Bu yanlış görünüyor. Kilit noktayı kaçırıyorsunuz. Aynı modülün içindeki ve farklı modüllerin içindeki sınıfları birbirinden ayırmanız gerekir. Farklı modüllerdeyse public, devralmanıza izin vermezler , bu nedenle 3. görüntü yanlıştır. Ayrıca, görebiliyorsanız, herhangi bir sınıfa her zaman bir uzantı ekleyebilirsiniz. Uzantılarda görünürlüğü açıklamak o zaman çok iyi bir fikir değildir.
Sulthan

Aslında, diyagramımın sadece aynı modülde çalıştığından bahsetmeliyim, bu nedenle 3. resim sadece kullanıcının hızlı bir şekilde anlamasını istiyorum fileprivate sadece aynı dosya üzerinde çalışır.
Stephen Chen

6

Pratik bir kural, yalnızca sınıfınızın / yapınızın bildiriminde kullanılan değişkenler, sabitler, iç yapılar ve sınıflar için özel kullanmanızdır. Sınıfınız / yapınızla aynı dosya içinde, ancak küme parantezlerini tanımlamalarının (ör. Sözcüksel kapsamı) dışında uzantılarınızın içinde kullanılan şeyler için fileprivate öğesini kullanırsınız.

    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

Swift 4.0'da Özel'e artık uzantıda erişilebilir, ancak aynı dosya içinde. Başka bir dosyadaki uzantıyı bildirir / tanımlarsanız, özel değişkeninize uzantınız için erişilemez **

Dosya Özel
Dosya-özel erişim, bir varlığın kullanımını kendi tanımlayıcı kaynak dosyasına kısıtlar. Bu ayrıntılar bir dosya içinde kullanıldığında belirli bir işlevsellik parçasının uygulama ayrıntılarını gizlemek için dosya-özel erişimini kullanın.
Sözdizimi: fileprivate <var type> <variable name>
Örnek: fileprivate class SomeFilePrivateClass {}


Özel
Özel erişim, bir varlık kullanımını ekteki bildirimle ve bu bildirimin aynı dosyadaki uzantılarıyla sınırlar . Bu ayrıntılar yalnızca tek bir bildirimde kullanıldığında belirli bir işlevsellik parçasının uygulama ayrıntılarını gizlemek için özel erişimi kullanın.
Sözdizimi: private <var type> <variable name>
Örnek: private class SomePrivateClass {}


İşte tüm erişim düzeyleri hakkında daha fazla bilgi: Swift - Erişim Seviyeleri

Bu resimlere bakın:
Dosya: ViewController.swift
Burada uzantı ve görünüm denetleyicisinin her ikisi de aynı dosyada, bu nedenle özel değişken testPrivateAccessLeveluzantıda erişilebilir

resim açıklamasını buraya girin


Dosya: TestFile.swift
Burada uzantı ve görünüm denetleyicisi farklı dosyalardadır, bu nedenle özel değişken testPrivateAccessLeveluzantıda erişilemez.

resim açıklamasını buraya girin

resim açıklamasını buraya girin


Burada sınıf ViewController2bir alt sınıftır ViewControllerve her ikisi de aynı dosyadadır. Burada özel değişkene testPrivateAccessLevelAlt sınıfta erişilemez, ancak dosyaprivate değerine alt sınıfta erişilebilir.

resim açıklamasını buraya girin


5

@ MartinR ve @ StephenChen'in cevabı mükemmel olsa da, Swift 4 işleri biraz değiştiriyor.

Özel , artık bildirildiği bir sınıfa ve onun uzantılarına özel olarak kabul edilir.

FilePrivate , değişkenin tanımlandığı bir sınıf, uzantısı veya aynı dosyada tanımlanan diğer sınıflar olsun, bu dosyada özel olarak kabul edilir.


5

Swift 5 için güncellendi

Özel ve FilePrivate karşılaştırması

Daha iyi netlik için kod snippet'ini Playground'a yapıştırın

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

    }
}

Not : Swift dosyasının dışına hem private hem de fileprivate erişilemez.


4

filePrivate - erişim denetim düzeyi dosya içinde.

durum 1 : Aynı sınıf dosyasıyla uzantı oluşturursak ve uzantısında fileprivate işlevine veya fileprivate özelliğine erişmeye çalışırsak - erişimine izin verilir
durum 2 : Yeni dosyada sınıf uzantısı oluşturursak - Ve şimdi fileprivate işlevine veya fileprivate öğesine erişmeyi deneyin özellik - erişime izin verilmiyor

özel erişim kontrol düzeyi sözlüksel kapsamdadır

durum 1 : Özellik veya işlev sınıfta özel olarak bildirilirse - kapsam varsayılan olarak sınıftır. durum 2 : özel örnek işlev gövdesinde ile bildirilirse - örnek kapsamı işlev gövdesi ile sınırlıdır.


3

Aşağıdaki örnekte, dil yapıları değiştirilmiş privateve fileprivateaynı şekilde davranmıştır:

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

Bu sezgiye göre, sanırım. Ancak, bir istisna var mı?

Saygılarla.


3

Hızlı 4 için açıklama budur. Hızlı 3 için fark özeldir. swift 3 private, uzantısıyla erişilemez, yalnızca A Sınıfının kendisi erişebilir.

resim açıklamasını buraya girin Hızlı 4'ten sonra, kişi normalde aynı dosyadaki alt sınıfı tanımlamayacağından fileprivate öğesi biraz gereksiz olur. Özel çoğu vaka için yeterli olmalıdır.


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

}

Bunu seviyorum çünkü ivars için süper basit.

Fileprivate öğesini özel olarak değiştirmeyi deneyin (ya da tam tersi) ve derlemede ne olduğunu görün ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.