2016-08-18 14 views
104

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

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

ответ

212

fileprivate теперь, что private раньше в предыдущих Swift релизы: доступные из того же исходного файла. Объявление, помеченное как 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).

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

Примечания:

  1. Предложение SE-0159 – Fix Private Access Levels предложил вернуться к Swift 2 семантике Swift 4. После длительной и противоречивой дискуссии о быстроногих эволюции в списке рассылки, предложение было rejected.

  2. Предложение SE-0169 – Improve Interaction Between private Declarations and Extensions предлагает сделать private деклараций внутри типа, доступной для расширения одного и того же типа , если расширение определяется в же исходном файле. Это предложение было принято и реализовано в Swift 4.

+2

Если вы автоматически конвертируете код из Swift 2 в 3, Xcode превратит 'private' в' fileprivate'. Однако, если у вас есть роскошь делать это вручную, вы можете часто получать выгоду от того, чтобы оставить 'private' как' private' ... если он компилируется, все хорошо. –

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

} 

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

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

4

Практического правила заключается в том, что вы используете частным переменные, константы, внутренние структуры и классы, которые используются только внутри объявления вашего класса/структуры. Вы используете 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 
     } 
    } 
56

Я просто нарисовать диаграмму о частном, fileprivate, открыть, закрыть

Надеется, что это может быстро помочь вам, для текстового описания смотрите ответ Martin R «s

Нового

Спасибо за Ответ Sulthan. Эта схема работает только на одном модуле

enter image description here

+6

Следите, 'fileprivate' не связан с расширением, а с файлом (запись расширения класса A в другой файл не позволит использовать члены' fileprivate') – Vince

+1

, а также thx @Vince исправить мою ошибку. :) –

+1

Это кажется неправильным. Вам не хватает ключевого момента. Вы должны различать классы, которые находятся внутри одного и того же модуля и находятся в разных модулях. Если они находятся в разных модулях, то «public» не позволит вам наследовать, поэтому третье изображение неверно.Кроме того, вы всегда можете поместить расширение в любой класс, если сможете его увидеть. Объяснение видимости в расширениях - это не очень хорошая идея. – Sulthan

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

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

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

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

0

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

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


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


Здесь более подробно обо всех уровней доступа: Swift - Access Levels

Посмотрите на это изображения:
Файл: 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

0

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

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^