什么是区分 Swift3 中的 fileprivate 和 private 的好例子
What is a good example to differentiate between fileprivate and private in Swift3
article 有助于理解 Swift 3
中的新访问说明符。它还给出了 fileprivate
和 private
的不同用法的一些示例。
我的问题是 - 在将仅在此文件中使用的函数上使用 fileprivate
是否与使用 private
相同?
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 suggested to revert to the Swift 2 semantics in Swift 4. After a lengthy and controversial discussion on the swift-evolution mailing list, the proposal was rejected.
提案SE-0169 – Improve Interaction Between private Declarations and Extensions建议制作private
同一类型的扩展可访问的类型内的声明
如果扩展名在 相同的源文件中定义。
该提议在 Swift 4.
中被接受并实施
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(反之亦然),看看编译时会发生什么...
一个实用的经验法则是,您对仅在 class / 结构的声明中使用的变量、常量、内部结构和 classes 使用 private。您将 fileprivate 用于与 class/struct 相同的文件中的扩展内部使用的东西,但在它们定义的大括号之外(即它们的词法范围)。
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、open和[=19的图=]public
希望能尽快帮到您,文字说明请参考Martin R的回答
[更新 Swift 4, 5 ]
在以下示例中,由 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))
我猜这是根据直觉。但是,有没有例外呢?
最诚挚的问候。
尽管@MartinR 和@StephenChen 的回答是完美的,Swift 4 稍微改变了一些。
Private 现在被认为是声明它的 class 及其扩展的私有。
FilePrivate 在该文件中被认为是私有的,无论是定义变量的 class、它的扩展名,还是任何其他 class es 在同一文件中定义。
在 Swift 4.0 中,Private 现在可以在扩展中访问,但在同一文件中。如果您在其他文件中 declare/define 扩展名,那么您的扩展名将无法访问您的私有变量**
文件私有
文件私有访问将实体的使用限制在其自己的定义源文件中。当在整个文件中使用这些细节时,使用文件私有访问来隐藏特定功能的实现细节。
语法: 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
在扩展中不可访问。
这里 class ViewController2
是 ViewController
的子 class 并且都在同一个文件中。这里私有变量 testPrivateAccessLevel
在 Subclass 中不可访问,但 fileprivate 在 subclass.
中可访问
filePrivate - 访问控制级别在文件内。
案例 1:如果我们在同一个 class 文件中创建扩展,并尝试在其扩展中访问 fileprivate 函数或 fileprivate 属性 - 允许访问
案例 2:如果我们在新文件中创建 class 的扩展 - 现在尝试访问 fileprivate 函数或 fileprivate 属性 - 不允许访问
private - 访问控制级别在词法范围内
案例 1:如果 属性 或函数在 class 中声明为私有 - 那么范围默认为 class。
案例 2:如果在函数体中声明了私有实例 - 那么实例的范围仅限于函数体。
这是对swift4的解释,对于swift3,区别是私有的。 swift3 private不能被其扩展访问,只有ClassA本身可以访问
swift4之后,fileprivate就变得有点多余了,因为人们一般不会在同一个文件中定义子类。对于大多数情况,私有应该足够了。
更新 Swift 5
Private 对比 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 文件之外,私有文件和私有文件都不可访问。
article 有助于理解 Swift 3
中的新访问说明符。它还给出了 fileprivate
和 private
的不同用法的一些示例。
我的问题是 - 在将仅在此文件中使用的函数上使用 fileprivate
是否与使用 private
相同?
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 suggested to revert to the Swift 2 semantics in Swift 4. After a lengthy and controversial discussion on the swift-evolution mailing list, the proposal was rejected.
提案SE-0169 – Improve Interaction Between private Declarations and Extensions建议制作
private
同一类型的扩展可访问的类型内的声明 如果扩展名在 相同的源文件中定义。 该提议在 Swift 4. 中被接受并实施
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(反之亦然),看看编译时会发生什么...
一个实用的经验法则是,您对仅在 class / 结构的声明中使用的变量、常量、内部结构和 classes 使用 private。您将 fileprivate 用于与 class/struct 相同的文件中的扩展内部使用的东西,但在它们定义的大括号之外(即它们的词法范围)。
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、open和[=19的图=]public
希望能尽快帮到您,文字说明请参考Martin R的回答
[更新 Swift 4, 5 ]
在以下示例中,由 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))
我猜这是根据直觉。但是,有没有例外呢?
最诚挚的问候。
尽管@MartinR 和@StephenChen 的回答是完美的,Swift 4 稍微改变了一些。
Private 现在被认为是声明它的 class 及其扩展的私有。
FilePrivate 在该文件中被认为是私有的,无论是定义变量的 class、它的扩展名,还是任何其他 class es 在同一文件中定义。
在 Swift 4.0 中,Private 现在可以在扩展中访问,但在同一文件中。如果您在其他文件中 declare/define 扩展名,那么您的扩展名将无法访问您的私有变量**
文件私有
文件私有访问将实体的使用限制在其自己的定义源文件中。当在整个文件中使用这些细节时,使用文件私有访问来隐藏特定功能的实现细节。
语法: 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
在扩展中不可访问。
这里 class ViewController2
是 ViewController
的子 class 并且都在同一个文件中。这里私有变量 testPrivateAccessLevel
在 Subclass 中不可访问,但 fileprivate 在 subclass.
filePrivate - 访问控制级别在文件内。
案例 1:如果我们在同一个 class 文件中创建扩展,并尝试在其扩展中访问 fileprivate 函数或 fileprivate 属性 - 允许访问
案例 2:如果我们在新文件中创建 class 的扩展 - 现在尝试访问 fileprivate 函数或 fileprivate 属性 - 不允许访问
private - 访问控制级别在词法范围内
案例 1:如果 属性 或函数在 class 中声明为私有 - 那么范围默认为 class。 案例 2:如果在函数体中声明了私有实例 - 那么实例的范围仅限于函数体。
这是对swift4的解释,对于swift3,区别是私有的。 swift3 private不能被其扩展访问,只有ClassA本身可以访问
更新 Swift 5
Private 对比 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 文件之外,私有文件和私有文件都不可访问。