Что является хорошим примером для различения fileprivate и private в Swift3

Эта статья была полезной для понимания новых спецификаторов доступа в Swift 3. В нем также приводятся некоторые примеры различных применений fileprivate и private.

Мой вопрос: не использует fileprivate для функции, которая будет использоваться только в этом файле так же, как с помощью private?

Ответ 1

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 метод foo доступен только в рамках определения class A {... }. Он даже недоступен из расширения к типу (в Swift 3 см. Второе примечание ниже для изменений в Swift 4).

  • Метод приватно файловой bar доступен из того же исходного файла.

Заметки:

  1. В предложении SE-0159 - "Исправить уровни частного доступа" предлагается вернуться к семантике Swift 2 в Swift 4. После продолжительного и противоречивого обсуждения списка рассылки swift-evolution предложение было отклонено.

  2. Предложение SE-0169 - Улучшение взаимодействия между частными объявлениями и расширениями предлагает сделать private объявления внутри типа доступными для расширений одного типа, если расширение определено в том же исходном файле. Это предложение было принято и реализовано в Swift 4.

Ответ 2

Я просто рисую диаграмму о частном, частном, открытом и публичном

Надеюсь, это поможет вам быстро, текстовое описание см. В ответе Martin R

[Обновление Swift 4]

enter image description here

Ответ 3

Практическое эмпирическое правило состоит в том, что вы используете 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
        }
    }

Ответ 4

В Swift 4.0 Private теперь доступен в расширении, но в том же файле. Если вы объявите/определите расширение в другом файле, ваша личная переменная не будет доступна вашему расширению **

Файл закрытый
Частный доступ к файлу ограничивает использование объекта собственным определяющим исходным файлом. Используйте частный доступ к файлу, чтобы скрыть детали реализации определенной части функциональности, когда эти детали используются во всем файле.
Синтаксис: fileprivate <var type> <variable name>
Пример: fileprivate class SomeFilePrivateClass {}


Частный
Частный доступ ограничивает использование объекта прилагаемой декларацией и расширениями этой декларации, которые находятся в том же файле. Используйте частный доступ, чтобы скрыть детали реализации определенной части функциональности, когда эти детали используются только в пределах одной декларации.
Синтаксис: private <var type> <variable name>
Пример: private class SomePrivateClass {}


Вот более подробно обо всех уровнях доступа: Swift - Уровни доступа

Посмотрите на эти изображения:
Файл: ViewController.swift
Здесь контроллер расширения и представления находятся в одном файле, поэтому в расширении доступна закрытая переменная testPrivateAccessLevel

enter image description here


Файл: TestFile.swift
Здесь контроллер расширения и представления находятся в разных файлах, поэтому закрытая переменная testPrivateAccessLevel недоступна в расширении.

enter image description here

enter image description here


Здесь класс ViewController2 является подклассом ViewController и оба находятся в одном файле. Здесь закрытая переменная testPrivateAccessLevel недоступна в подклассе, но fileprivate доступна в подклассе.

enter image description here

Ответ 5

Хотя ответы @MartinR и @StephenChen идеальны, Swift 4 немного меняет ситуацию.

Частный теперь считается закрытым для класса, в котором он объявлен, а также его расширений.

FilePrivate считается приватным в этом файле - это класс, в котором определена переменная, расширение или любые другие классы, определенные в этом же файле.

Ответ 6

В следующем примере языковые конструкции, измененные с помощью 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))

Это, согласно интуиции, я думаю. Но есть ли какие-либо исключения?

С наилучшими пожеланиями.

Ответ 7

Это объяснение для swift 4. Для swift 3 разница - частная. swift 3 private не может быть доступен его расширением, только сам класс A может получить к нему доступ.

enter image description here После swift 4 fileprivate становится немного избыточным, потому что обычно человек не определяет подкласс в том же файле. Частных должно быть достаточно для большинства случаев.

Ответ 8

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

}

Мне нравится это, потому что это очень просто для иваров.

Попробуйте изменить fileprivate на private (и наоборот) и посмотрите, что происходит при компиляции...

Ответ 9

filePrivate - уровень контроля доступа находится внутри файла.

case 1: если мы создаем расширение с одним и тем же файлом класса и попытаемся получить доступ к функции fileprivate или fileprivate в своем расширении - доступ разрешен case 2: если мы создадим расширение класса в новом файле - и теперь попробуйте получить доступ к функции fileprivate или fileprivate - доступ не разрешен

закрытый - уровень контроля доступа находится в лексической области

case 1: если свойство или функция объявлено как private в классе, то по умолчанию класс по умолчанию является классом. case 2: если частный экземпляр объявляется с телом функции, то область экземпляра ограничена телом функции.

Ответ 10

Обновлено для Swift 5

Личное против 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 недоступны.