在Swift3中区分fileprivate和private是一个很好的例子
本文有助于理解Swift 3
的新访问说明符。 它也给出了一些不同用法的fileprivate
和private
例子。
我的问题是 – 是不是使用fileprivate
函数将被使用只在这个文件中使用相同的private
?
fileprivate
现在是什么private
曾经在以前的Swift版本:可从同一个源文件访问。 标记为private
的声明现在只能在声明的词法范围内访问。所以private
比fileprivate
更具限制性。
示例(全部在一个源文件中):
class A { private func foo() {} fileprivate func bar() {} func baz() { foo() bar() } } extension A { func test() { foo() // error: use of unresolved identifier 'foo' bar() } } let a = A() a.foo() // error: 'foo' is inaccessible due to 'private' protection level a.bar()
-
私有
foo
方法只能在class A { ... }
定义的范围内访问。 甚至不能从扩展types访问(在Swift 3中,关于Swift 4的变化请参见下面的第二个注释)。 -
文件 – 专用
bar
方法可以从同一个源文件访问。
笔记:
-
build议SE-0159-修复了私有访问级别,build议在Swift 4中恢复Swift 2的语义。经过对迅速发展的邮件列表的漫长而有争议的讨论之后,提案被拒绝了 。
-
提案SE-0169 – 改进私有声明和扩展之间的交互build议,如果在相同的源文件中定义了扩展名,则可以在相同types的扩展中访问一个types的
private
声明。 这个提案在Swift 4被接受和实施。
我只是画一个关于私人,fileprivate,打开,closures的图表
希望它能快速帮助你,对于文字描述请看Martin R的答案
新
感谢Sulthan的回答。 此图只适用于相同的模块
一个实际的经验法则是,你使用私有的variables,常量,内部结构和类只用于你的类/结构的声明。 你可以在你的扩展中使用fileprivate,在你的类/结构所在的同一个文件中,但是在它们定义的大括号(即它们的词法范围)之外。
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 } }
在下面的例子中, private
和fileprivate
修改的语言结构似乎performance相同:
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))
我猜这是根据直觉。 但是,有没有例外?
最亲切的问候。
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(反之亦然),看看编译中会发生什么…
虽然@ MartinR和@ StephenChen的回答是完美的,但Swift 4改变了一些东西。
私人现在被认为是宣称的私人阶层,也是私人的扩展。
FilePrivate在该文件中被认为是私有的,无论是定义variables的类,扩展名还是在同一文件中定义的其他类。
在Swift 4.0中,Private现在可以在扩展中访问,但是在同一个文件中。 如果你在其他文件中声明/定义了扩展名,那么你的私有variables将不能被你的扩展访问**
文件私有
文件私有访问将实体的使用限制在自己定义的源文件中。 当在整个文件中使用这些细节时,使用文件私有访问来隐藏特定function的实现细节。
语法: fileprivate <var type> <variable name>
示例: fileprivate class SomeFilePrivateClass {}
私人的
私人访问限制了实体对封闭声明的使用,并限制了在同一文件中声明的扩展。 当这些细节仅在一个声明中使用时,使用私有访问来隐藏特定function的实现细节。
语法: private <var type> <variable name>
例如: private class SomePrivateClass {}
这里是关于所有访问级别的更多细节: Swift – 访问级别
看看这个图片:
文件: ViewController.swift
这里的扩展和视图控制器都在同一个文件,因此私有variablestestPrivateAccessLevel
可以扩展访问
文件: TestFile.swift
这里的扩展和视图控制器都在不同的文件,因此私有variablestestPrivateAccessLevel
不能在扩展中访问。
这里类ViewController2
是ViewController2
的一个子类,它们都在同一个文件中。 这里私有variablestestPrivateAccessLevel
在子类中是不可访问的,但是在子类中可以访问fileprivate。