Мой вопрос: не использует fileprivate
для функции, которая будет использоваться только в этом файле так же, как с помощью private
?
Что является хорошим примером для различения fileprivate и private в Swift3
Ответ 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
доступен из того же исходного файла.
Заметки:
-
В предложении SE-0159 - "Исправить уровни частного доступа" предлагается вернуться к семантике Swift 2 в Swift 4. После продолжительного и противоречивого обсуждения списка рассылки swift-evolution предложение было отклонено.
-
Предложение SE-0169 - Улучшение взаимодействия между частными объявлениями и расширениями предлагает сделать
private
объявления внутри типа доступными для расширений одного типа, если расширение определено в том же исходном файле. Это предложение было принято и реализовано в Swift 4.
Ответ 2
Я просто рисую диаграмму о частном, частном, открытом и публичном
Надеюсь, это поможет вам быстро, текстовое описание см. В ответе Martin R
[Обновление Swift 4]
Ответ 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
Файл: TestFile.swift
Здесь контроллер расширения и представления находятся в разных файлах, поэтому закрытая переменная testPrivateAccessLevel
недоступна в расширении.
Здесь класс ViewController2
является подклассом ViewController
и оба находятся в одном файле. Здесь закрытая переменная testPrivateAccessLevel
недоступна в подклассе, но fileprivate доступна в подклассе.
Ответ 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 может получить к нему доступ.
После 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 недоступны.