Який хороший приклад для розмежування файлового і приватного в Swift3


142

Ця стаття корисна для розуміння нових специфікаторів доступу в Swift 3. Тут також наводяться приклади різних звичаїв fileprivateта private.

Моє запитання - чи не використовується fileprivateфункція, яка буде використовуватися лише у цьому файлі, та сама, що і для використання private?

Відповіді:


282

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

  • Файлово-приватний barметод доступний з того самого вихідного файлу.

Примітки:

  1. Пропозиція SE-0159 - Виправити рівні приватного доступу запропонувала повернутися до семантики Swift 2 у Swift 4. Після тривалої та суперечливої ​​дискусії у списку розсилки швидкої еволюції пропозицію було відхилено .

  2. Пропозиція SE-0169 - Удосконалити взаємодію між приватними деклараціями та розширеннями пропонує зробити private декларації всередині типу доступними для розширень одного типу, якщо розширення визначено в одному вихідному файлі. Ця пропозиція була прийнята і реалізована в Swift 4.


2
Якщо ви автоматично перетворите код з Swift 2 в 3, Xcode перетвориться privateна fileprivate. Однак, якщо у вас є розкіш робити це вручну, ви можете часто отримати вигоду від того private, privateщоб виїхати, як ... якщо він збирає, все добре.
Дан Розенстарк

@DanielLarsson: Перегляньте свої пропозиції щодо редагування: Обидва коментарі стосуються foo()дзвінка.
Мартін Р

82

Я просто малюю схему про приватне , файлове , відкрите та загальнодоступне

Сподіваюся , що це може швидко допомогти вам, для текстового опису , будь ласка , зверніться до Martin R відповіді «s

[Оновити Swift 4]

введіть тут опис зображення


9
стежте, fileprivateне пов’язаний із розширенням, а з файлом (написання розширення класу A в інший файл не дозволить використовувати fileprivateучасників)
Vince

1
Це здається неправильним. Вам не вистачає ключового моменту. Ви повинні розмежовувати класи, які знаходяться всередині одного модуля і які знаходяться в різних модулях. Якщо вони знаходяться в різних модулях, то publicце не дозволить вам успадкувати, тому 3-те зображення є неправильним. Також ви завжди можете помістити розширення до будь-якого класу, якщо зможете його бачити. Пояснення наочності на розширеннях - це не дуже гарна ідея.
Султан

На самом деле, я повинен згадати мої діаграми роботи тільки на тому ж модулі, тому 3 - зображення , яке я просто хочу користувачеві швидко зрозуміти fileprivate працює тільки на тому ж файлі.
Стівен Чен

6

Практичне правило полягає в тому, що ви використовуєте приватні для змінних, констант, внутрішніх структур та класів, які використовуються лише всередині декларації вашого класу / структури. Ви використовуєте 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 приватне тепер доступне в розширенні, але в межах одного файлу. Якщо ви оголосите / визначите розширення в іншому файлі, то ваша приватна змінна не буде доступною для вашого розширення **

Файл
приватного доступу до файлів - приватний доступ до файлу обмежує використання сутності власним визначаючим вихідним файлом. Використовуйте приватний доступ до файлів, щоб приховати деталі реалізації певного фрагмента функціональності, коли ці дані використовуються в цілому файлі.
Синтаксис: 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недоступна в підкласі, але файлприват доступний у підкласі.

введіть тут опис зображення


5

Хоча відповіді @ MartinR та @ StephenChen ідеальні, Swift 4 дещо змінює речі.

Приватне зараз вважається приватним для класу, в якому він оголошений, а також до його розширень.

FilePrivate вважається приватним у цьому файлі, будь то клас, у якому визначена змінна, це розширення або будь-які інші класи, визначені в тому самому файлі.


5

Оновлено для 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 не доступні приватні та приватні файли.


4

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

випадок 1 : Якщо ми створимо розширення з тим самим файлом класу і спробуємо отримати доступ до функції fileprivate або до власності fileprivate в його розширенні - доступ дозволений
випадок 2 : Якщо ми створимо розширення класу в новому файлі - А тепер спробуємо отримати доступ до функції fileprivate або fileprivate власність - доступ заборонений

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

випадок 1 : Якщо властивість або функція оголошена приватною у класі - тоді область за замовчуванням є класом. випадок 2 : якщо приватний екземпляр оголошено функцією в тілі функції, то область примірника обмежується функціональним органом.


3

У наступному прикладі мовні конструкції модифікуються 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

Це пояснення для швидкого 4. Для swift 3 різниця приватна. swift 3 private не може отримати доступ до його розширення, лише клас A може отримати доступ.

введіть тут опис зображення Після swift 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()
    }

}

Мені це подобається, тому що це супер просто для ivars.

Спробуйте змінити fileprivate на приватний (і навпаки) і подивіться, що відбувається при компіляції ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.