在Swift3中区分fileprivate和private是一个很好的例子

本文有助于理解Swift 3的新访问说明符。 它也给出了一些不同用法的fileprivateprivate例子。

我的问题是 – 是不是使用fileprivate函数将被使用只在这个文件中使用相同的private

fileprivate现在是什么private曾经在以前的Swift版本:可从同一个源文件访问。 标记为private的声明现在只能在声明的词法范围内访问。所以privatefileprivate更具限制性。

示例(全部在一个源文件中):

 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方法可以从同一个源文件访问。

笔记:

  1. build议SE-0159-修复了私有访问级别,build议在Swift 4中恢复Swift 2的语义。经过对迅速发展的邮件列表的漫长而有争议的讨论之后,提案被拒绝了 。

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

在下面的例子中, privatefileprivate修改的语言结构似乎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不能在扩展中访问。

在这里输入图像描述

在这里输入图像描述

这里类ViewController2ViewController2的一个子类,它们都在同一个文件中。 这里私有variablestestPrivateAccessLevel在子类中是不可访问的,但是在子类中可以访问fileprivate。

在这里输入图像描述