Swift3에서 fileprivate과 private을 구별하는 좋은 예는 무엇입니까?


142

기사 는의 새로운 액세스 지정자를 이해하는 데 도움이되었습니다 Swift 3. 또한 서로 다른 용도의 몇 가지 예 제공 fileprivateprivate.

내 질문은- fileprivate이 파일에서만 사용할 함수에서 사용하지 않는 것 private입니까?

답변:


282

fileprivate무엇 지금 private같은 소스 파일에서 액세스 : 이전 스위프트 릴리스에서 사용. 로 표시된 선언 private은 선언 된 어휘 범위 내에서만 액세스 할 수 있습니다. 따라서 private보다 제한적 fileprivate입니다.

현재 스위프트 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방법은 동일한 소스 파일에서 액세스 할 수 있습니다.

노트:

  1. 제안 SE-0159 - 수정 개인 액세스 수준은 신속한 진화 메일 링리스트에 긴 논쟁적인 토론 후 스위프트 4의 스위프트 2 의미로 되돌릴 제안은 제안했다 거절 .

  2. 제안 SE-0169은 - 개인 선언 및 확장 사이의 상호 작용을 향상을 만들기 위해 제안 private 확장이 정의되어있는 경우 동일한 유형의 확장에 액세스 할 수있는 형식 안에 선언을 동일한 소스 파일입니다. 이 제안은 Swift 4에서 수락 및 이행되었습니다.


2
당신이 3 스위프트 2에서 자동으로 코드를 변환하는 경우, 엑스 코드가 켜집니다 privatefileprivate. 당신이 손으로 그 일의 고급 스러움이있는 경우 그러나, 당신은 종종 떠나 혜택을 누릴 수 있습니다 private으로 private... 그것은 컴파일하는 경우, 모든 좋은.
Dan Rosenstark

@DanielLarsson : 편집 제안 다시 작성 : 의견 모두foo() 통화에 적용됩니다 .
Martin R

82

나는 private , fileprivate , openpublic에 대한 다이어그램을 그립니다.

텍스트 설명은 Martin R 의 답변을 참조하십시오.

[스위프트 4 업데이트]

여기에 이미지 설명을 입력하십시오


9
조심 fileprivate하십시오, 확장명에 연결되어 있지 않지만 파일에 연결되어 있습니다 (다른 파일에 클래스 A의 확장명을 작성하면 fileprivate멤버를 사용할 수 없습니다 )
Vince

1
이것은 잘못된 것 같습니다. 핵심 사항이 없습니다. 동일한 모듈 내에 있고 다른 모듈에있는 클래스를 구별해야합니다. 서로 다른 모듈에 있으면 public상속 할 수 없으므로 세 번째 이미지가 올바르지 않습니다. 또한 볼 수 있으면 언제든지 모든 클래스에 확장을 둘 수 있습니다. 확장에 대한 가시성을 설명하는 것은 좋은 생각이 아닙니다.
Sulthan

사실, 내 다이어그램이 동일한 모듈에서만 작동한다는 것을 언급해야하므로 세 번째 이미지는 사용자가 fileprivate 가 동일한 파일에서만 작동 한다는 것을 빨리 이해하기를 원합니다 .
Stephen Chen

6

실제 경험의 규칙은 클래스 / 구조체 선언에서만 사용되는 변수, 상수, 내부 구조체 및 클래스에 대해 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

Swift 4.0에서는 이제 Private에서 확장명으로 액세스 할 수 있지만 동일한 파일 내에서 액세스 할 수 있습니다. 다른 파일에서 확장명을 선언 / 정의하면 확장에 개인 변수에 액세스 할 수 없습니다 **

파일 개인
파일 개인 액세스는 엔티티 사용을 자체 정의 소스 파일로 제한합니다. 파일 개인 액세스를 사용하여 세부 사항이 전체 파일 내에서 사용될 때 특정 기능의 구현 세부 사항을 숨기십시오.
구문 : fileprivate <var type> <variable name>
예 : fileprivate class SomeFilePrivateClass {}


개인
개인 액세스는 엔터티 사용을 엔 클로징 선언 및 동일한 파일에있는 해당 선언의 확장으로 제한 합니다 . 세부 사항이 단일 선언 내에서만 사용되는 경우 개인 액세스를 사용하여 특정 기능의 구현 세부 사항을 숨기십시오.
구문 : private <var type> <variable name>
예 : private class SomePrivateClass {}


모든 액세스 수준에 대한 자세한 내용은 다음과 같습니다. Swift-액세스 수준

이 이미지를보십시오 :
File : ViewController.swift
확장과 뷰 컨트롤러는 모두 같은 파일에 있으므로, 개인 변수 testPrivateAccessLevel는 확장에서 접근 할 수 있습니다

여기에 이미지 설명을 입력하십시오


File : TestFile.swift
확장과 뷰 컨트롤러는 서로 다른 파일에 있으므로, 개인 변수 testPrivateAccessLevel는 확장에 접근 할 수 없습니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


여기서 class ViewController2는의 서브 클래스 ViewController이며 둘 다 동일한 파일에 있습니다. 여기서 개인 변수 testPrivateAccessLevel는 서브 클래스에서 액세스 할 수 없지만 fileprivate는 서브 클래스에서 액세스 할 수 있습니다.

여기에 이미지 설명을 입력하십시오


5

@MartinR과 @StephenChen의 답변은 완벽하지만 Swift 4 는 약간 변경합니다.

Private 은 이제 클래스가 선언 된 클래스와 확장 클래스에 대해 private으로 간주됩니다.

FilePrivate 는 변수가 정의 된 클래스, 확장명 또는 동일한 파일에 정의 된 다른 클래스이기 때문에 해당 파일에서 개인용으로 간주됩니다.


5

스위프트 5 업데이트

비공개FilePrivate

명확성을 높이기 위해 코드 스 니펫을 놀이터에 붙여 넣기

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 파일 외부에서는 개인 및 파일 개인 모두에 액세스 할 수 없습니다.


4

filePrivate- 액세스 제어 레벨이 파일 내에 있습니다.

사례 1 : 동일한 클래스 파일로 확장자를 작성하고 확장자로 fileprivate 함수 또는 fileprivate 특성에 액세스하려고 시도-액세스 허용
사례 2 : 새 파일에서 클래스 확장자를 작성하는 경우-이제 fileprivate 함수 또는 fileprivate에 액세스하십시오 재산-접근 금지

개인용 액세스 제어 수준은 어휘 범위에 있습니다

case 1 : 클래스에서 속성 또는 함수가 private으로 선언 된 경우 범위는 기본적으로 클래스입니다. case 2 : 개인 인스턴스가 함수 본문에서 선언되면 인스턴스 범위는 함수 본문으로 제한됩니다.


3

다음 예에서 언어 구조에 의해 수정 privatefileprivate동일하게 작동하는 것 :

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

이것은 스위프트 4에 대한 설명입니다. 스위프트 3의 경우 차이점은 사적인 것입니다. swift 3 private은 확장 기능으로 액세스 할 수 없으며 클래스 A 자체 만 액세스 할 수 있습니다.

여기에 이미지 설명을 입력하십시오 신속한 4 이후, 개인은 일반적으로 동일한 파일에서 서브 클래스를 정의하지 않기 때문에 fileprivate는 약간 중복됩니다. 대부분의 경우 개인이면 충분합니다.


1
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으로 변경하거나 그 반대로 변경하여 컴파일시 어떤 일이 발생하는지 확인하십시오 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.