此article有助于了解Swift 3
中的新访问说明符。它还提供了fileprivate
和private
的不同用法的一些示例。
我的问题是 - 对于仅在此文件中使用的函数使用fileprivate
是否与使用private
相同?
答案 0 :(得分:269)
fileprivate
现在是private
之前的状态
Swift版本:可从中获取
相同的源文件。标记为private
的声明现在只能在声明它的词法范围内访问。
因此private
比fileprivate
更具限制性。
从 Swift 4开始,如果扩展名在同一源文件中定义,则类型内的私有声明可以被相同类型的扩展访问。
示例(所有在一个源文件中):
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()
私有foo
方法只能在范围内访问
class A { ... }
定义。它甚至无法访问
类型的扩展(在Swift 3中,请参阅下面的第二个注释
Swift中的变化4)。
可以从同一源文件访问文件私有bar
方法。
注意:
提案SE-0159 – Fix Private Access Levels建议恢复Swift 4中的Swift 2语义。经过对swift-evolution邮件列表的冗长而有争议的讨论,该提案为rejected。
提案SE-0169 – Improve Interaction Between private Declarations and Extensions建议private
在同一类型的扩展可访问的类型内的声明
如果扩展名在相同的源文件中定义。
该提案在Swift 4中被接受并实施。
答案 1 :(得分:77)
答案 2 :(得分:6)
一个实际的经验法则是对变量,常量,内部结构和仅在类/结构声明中使用的类使用private。您可以将fileprivate用于与您的类/结构相同的文件中的扩展内部使用的内容,但在其定义的花括号之外(即它们的词法范围)。
struct Person {
let firstName: String
let lastName: String
}
答案 3 :(得分:5)
在Swift 4.0中,Private现在可以在扩展名中访问,但在同一个文件中。如果您在其他文件中声明/定义扩展名,则您的扩展程序将无法访问您的私有变量**
文件专用
文件专用访问将实体的使用限制在其自己的定义源文件中。当在整个文件中使用这些详细信息时,使用文件专用访问来隐藏特定功能的实现细节。
语法: fileprivate <var type> <variable name>
示例: fileprivate class SomeFilePrivateClass {}
的私人强>
私人访问限制实体对封闭声明的使用,以及对同一文件中声明的扩展的限制。当这些详细信息仅在单个声明中使用时,使用私有访问来隐藏特定功能的实现细节。
语法: private <var type> <variable name>
示例: private class SomePrivateClass {}
以下是有关所有访问级别的详细信息:Swift - Access Levels
看看这张图片:
文件: ViewController.swift
这里扩展和视图控制器都在同一个文件中,因此私有变量testPrivateAccessLevel
可以在扩展名
文件: TestFile.swift
这里的扩展和视图控制器都在不同的文件中,因此扩展名中无法访问私有变量testPrivateAccessLevel
。
这里,类ViewController2
是ViewController
的子类,两者都在同一个文件中。此处私有变量testPrivateAccessLevel
在子类中不可访问,但fileprivate可在子类中访问。
答案 4 :(得分:4)
虽然@ MartinR和@ StephenChen的回答是完美的,但 Swift 4 会改变一些事情。
私有现在被视为对其声明的类及其扩展名的私有。
FilePrivate 在该文件中被视为私有,无论是定义变量的类,扩展名还是同一文件中定义的任何其他类。
答案 5 :(得分:3)
在以下示例中,由private
和fileprivate
修改的语言结构似乎行为相同:
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))
这是根据直觉,我猜。但是,有什么例外吗?
最诚挚的问候。
答案 6 :(得分:2)
这是swift 4的解释。对于swift 3,区别是私有的。 swift 3 private无法通过其扩展名访问,只有A类本身可以访问。
答案 7 :(得分:2)
已为Swift 5更新
私有与 FilePrivate
为清楚起见,将代码段粘贴到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
}
}
注意:在Swift文件之外,私有文件和文件私有文件均无法访问。
答案 8 :(得分: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()
}
}
我喜欢这个,因为它对于ivars来说非常简单。
尝试将fileprivate更改为private(反之亦然),看看编译时会发生什么......