web-dev-qa-db-ja.com

Swift3でfileprivateとprivateを区別する良い例は何ですか

この 記事 は、Swift 3の新しいアクセス指定子を理解するのに役立ちました。また、fileprivateおよびprivateのさまざまな使用法の例を示します。

私の質問は-fileprivateを使用するのと同じように、このファイルでのみ使用される関数でprivateを使用していないのですか?

132
Nikita P

fileprivateは、以前のSwiftリリースで使用されていたprivateになりました。同じソースファイルからアクセスできます。 privateとしてマークされた宣言は、宣言されたレキシカルスコープ内でのみアクセスできるようになりました。したがって、privatefileprivateよりも制限が厳しくなります。

Swift 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番目の注意を参照してください)。

  • ファイルプライベートbarメソッドは、同じソースファイルからアクセスできます。

注:

  1. 提案 SE-0159 –プライベートアクセスレベルの修正 SwiftのSwift 2セマンティクスに戻すことを提案しました。 -evolutionメーリングリスト、提案は 拒否 でした。

  2. 提案 SE-0169 –プライベート宣言と拡張機能間の相互作用の改善 は、拡張機能がsameで定義されている場合、同じ型の拡張機能がアクセスできる型内のprivate宣言を作成することを提案しますソースファイル。この提案はSwiftで受け入れられ、実装されました4。

271
Martin R

私はprivatefileprivateopenおよびpublic

テキストの説明については、Martin Rの回答を参照してください。

[Update Swift 4]

enter image description here

77
Stephen Chen

実用的な経験則として、クラス/構造体の宣言内でのみ使用される変数、定数、内部構造体、およびクラスにはprivateを使用します。 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
        }
    }
6
Josh Homann

Swift 4.0では、プライベートで同じファイル内の拡張子でアクセスできるようになりました。他のファイルで拡張機能を宣言/定義すると、プライベート変数は拡張機能からアクセスできなくなります**

ファイルプライベート
ファイルプライベートアクセスは、エンティティの使用を独自の定義ソースファイルに制限します。ファイルプライベートアクセスを使用して、特定の機能の詳細がファイル全体で使用されている場合、それらの詳細を非表示にします。
構文:fileprivate <var type> <variable name>
例:fileprivate class SomeFilePrivateClass {}


プライベート
プライベートアクセスは、エンティティの使用を囲んでいる宣言と、同じファイル内のその宣言の拡張に制限します。プライベートアクセスを使用して、特定の機能の実装の詳細を隠しますこれらの詳細は、単一の宣言内でのみ使用されます。
構文:private <var type> <variable name>
例:private class SomePrivateClass {}


すべてのアクセスレベルの詳細を次に示します。 Swift-Access Levels

この画像を見てください:
ファイル:ViewController.Swift
ここで、拡張機能とView Controllerは両方とも同じファイルにあるため、プライベート変数testPrivateAccessLevelは拡張機能でアクセス可能です

enter image description here


ファイル:TestFile.Swift
ここで、拡張機能とView Controllerは両方とも異なるファイルにあるため、プライベート変数testPrivateAccessLevelは拡張機能ではアクセスできません。

enter image description here

enter image description here


ここで、クラスViewController2ViewControllerのサブクラスであり、両方が同じファイルにあります。ここで、プライベート変数testPrivateAccessLevelはサブクラスではアクセスできませんが、fileprivateはサブクラスでアクセスできます。

enter image description here

5
Krunal

@MartinRと@StephenChenの答えは完璧ですが、Swift 4は物事を少し変えます。

Privateは、宣言されたクラスおよびその拡張に対してプライベートと見なされるようになりました。

FilePrivateは、変数が定義されているクラス、その拡張子、または同じファイルで定義されている他のクラスであっても、そのファイルではプライベートと見なされます。

4
Nikita P

次の例では、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))

これは直感によると思います。しかし、例外はありますか?

よろしくお願いします。

3
Tomas Balderas

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の両方にアクセスできません。

2
Arpit Jain

これはSwift 4の説明です。Swift 3の場合、違いはプライベートです。 Swift 3 privateはその拡張によってアクセスできません。クラスAのみがアクセスできます。

enter image description here Swift 4の後、fileprivateは少し冗長になります。これは、通常、同じファイルでサブクラスを定義しないためです。ほとんどの場合、プライベートで十分です。

2
Weidian Huang

filePrivate-アクセス制御レベルはファイル内にあります。

ケース1:同じクラスファイルで拡張機能を作成し、その拡張機能でfileprivate関数またはfileprivateプロパティにアクセスしようとした場合-アクセスが許可されました
ケース2:新しいファイルにクラスの拡張子を作成する場合-そして、今度はfileprivate関数またはfileprivateプロパティにアクセスしてください-アクセスは許可されません

プライベート-アクセス制御レベルはレキシカルスコープ内にあります

ケース1:プロパティまたは関数がクラスでプライベートとして宣言されている場合-スコープはデフォルトでクラスです。 ケース2:プライベートインスタンスが関数本体で宣言されている場合-インスタンスのスコープは関数本体に制限されます。

2
Ashish Chhabra
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(またはその逆)に変更してみて、コンパイル時に何が起こるかを確認してください...

1
CPD