回答:
fileprivate
これはprivate
、以前のSwiftリリースで使用されていたものです。同じソースファイルからアクセスできます。としてマークされた宣言は、宣言されprivate
たレキシカルスコープ内でのみアクセスできるようになりました。そのprivate
ため、よりも制限されfileprivate
ます。
とおりスウィフト4、拡張子が同じソースファイルで定義されている場合タイプ内部のプライベートな宣言は、同じタイプの拡張にアクセスできます。
例(すべて1つのソースファイル内):
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での変更点については、下の2番目のメモを参照してください)。
file-private bar
メソッドは、同じソースファイルからアクセスできます。
ノート:
提案SE-0159 – Swift 4でSwift 2のセマンティクスに戻すよう提案されたプライベートアクセスレベルを修正しました。Swift-evolutionメーリングリストでの長く議論の多い議論の後、提案は拒否されました。
提案SE-0169 –プライベート宣言と拡張間の相互作用を改善private
するは、拡張が同じソースファイルで定義されている場合、同じ型の拡張からアクセスできる型内の宣言を作成することを提案します。
この提案はSwift 4で受け入れられ、実装されました。
foo()
通話に適用されます。
fileprivate
拡張子にリンクされていませんが、ファイルにリンクされています(クラスAの拡張子を別のファイルに書き込んでも、fileprivate
メンバーの使用は許可されません)
public
場合、継承を許可しないため、3番目のイメージは正しくありません。また、拡張機能が表示されている場合は、いつでも任意のクラスに拡張機能を配置できます。その場合、拡張機能の可視性を説明することはあまり良い考えではありません。
実際の経験則では、クラス/構造体の宣言内でのみ使用される変数、定数、内部構造体、およびクラスにプライベートを使用します。class / structと同じファイル内の拡張機能の内部で使用されているが、それらの定義中括弧(つまり、レキシカルスコープ)の外部で使用されるものには、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
}
}
Swift 4.0では、Privateが拡張機能でアクセスできますが、同じファイル内にあります。他のファイルで拡張子を宣言/定義すると、プライベート変数は拡張子にアクセスできなくなります**
ファイルプライベート
ファイルプライベートアクセスは、エンティティの使用をそれ自体の定義ソースファイルに制限します。ファイルプライベートアクセスを使用して、特定の機能の実装の詳細がファイル全体で使用されている場合に、それらの詳細を非表示にします。
構文: fileprivate <var type> <variable name>
例: fileprivate class SomeFilePrivateClass {}
プライベート
プライベートアクセスは、エンティティの使用を、囲んでいる宣言、および同じファイル内にあるその宣言の拡張に制限します。特定の機能の実装の詳細が単一の宣言内でのみ使用される場合は、プライベートアクセスを使用して、特定の機能の実装の詳細を非表示にします。
構文: private <var type> <variable name>
例: private class SomePrivateClass {}
すべてのアクセスレベルの詳細は次のとおりです。Swift-アクセスレベル
この画像を見てください:
ファイル: ViewController.swift
ここでは、拡張機能とビューコントローラーの両方が同じファイルにあるためtestPrivateAccessLevel
、拡張機能でプライベート変数にアクセスできます。
ファイル: TestFile.swift
ここでは、拡張機能とビューコントローラーの両方が異なるファイルにあるためtestPrivateAccessLevel
、拡張機能ではプライベート変数にアクセスできません。
ここで、クラスViewController2
はのサブクラスでViewController
あり、両方が同じファイルにあります。ここで、プライベート変数testPrivateAccessLevel
はサブクラスではアクセスできませんが、fileprivateはサブクラスでアクセスできます。
Swift 5用に更新
プライベート vs 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ファイルの外では、privateとfileprivateの両方にアクセスできません。
filePrivate-アクセス制御レベルはファイル内にあります。
ケース1:同じクラスファイルで拡張子を作成し、その拡張子でfileprivate関数またはfileprivateプロパティにアクセスしようとした
場合 -アクセス許可ケース2:新しいファイルでクラスの拡張子を作成した場合-そして、fileprivate関数またはfileprivateにアクセスしようとしますプロパティ-アクセスは許可されていません
private-アクセス制御レベルはレキシカルスコープ内にあります
ケース1:プロパティまたは関数がクラスでプライベートとして宣言されている場合、スコープはデフォルトでクラスになります。 ケース2:プライベートインスタンスが関数本体で宣言されている場合-インスタンスのスコープは関数本体に限定されます。
次の例では、によって変更され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))
これは直感によると思います。しかし、例外はありますか?
よろしくお願いします。
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()
}
}
ivarは非常にシンプルなので、私はこれが好きです。
fileprivateをprivate(およびその逆)に変更して、コンパイル時に何が起こるかを確認してください...
private
なりfileprivate
ます。あなたが手でそれを行うことの贅沢を持っている場合は、あなたは、多くの場合、残しての恩恵を受けることができるprivate
ようprivate
...それは、すべての良いをコンパイルする場合。