Yanıtlar:
fileprivate
şimdi private
daha önceki Swift sürümlerinde olan şeydi : aynı kaynak dosyadan erişilebilir. private
Artık olarak bildirildiği bildirime yalnızca bildirildiği sözcük kapsamı içinde erişilebilir. Öyleyse private
bundan 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 foo
yö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 bar
yöntemine aynı kaynak dosyadan erişilebilir.
Notlar:
Ö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 .
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ı.
foo()
çağrı için geçerlidir .
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]
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 )
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.
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
}
}
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 testPrivateAccessLevel
uzantıda erişilebilir
Dosya: TestFile.swift
Burada uzantı ve görünüm denetleyicisi farklı dosyalardadır, bu nedenle özel değişken testPrivateAccessLevel
uzantıda erişilemez.
Burada sınıf ViewController2
bir alt sınıftır ViewController
ve her ikisi de aynı dosyadadır. Burada özel değişkene testPrivateAccessLevel
Alt sınıfta erişilemez, ancak dosyaprivate değerine alt sınıfta erişilebilir.
@ 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.
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.
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.
Aşağıdaki örnekte, dil yapıları değiştirilmiş private
ve fileprivate
aynı ş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.
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 ...
private
dönüşecektirfileprivate
. Elle yapıyor lüks varsa Ancak, çoğu zaman terk yararlanabilirprivate
olarakprivate
... derler bile tüm iyi.