Respostas:
fileprivate
agora é o que private
costumava ser nas versões anteriores do Swift: acessíveis a partir do mesmo arquivo de origem. Uma declaração marcada como private
agora só pode ser acessada dentro do escopo lexical em que está declarada. Portanto, private
é mais restritiva que fileprivate
.
A partir do Swift 4, as declarações privadas dentro de um tipo são acessíveis a extensões do mesmo tipo se a extensão estiver definida no mesmo arquivo de origem.
Exemplo (tudo em um arquivo de origem):
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()
O foo
método privado é acessível apenas dentro do escopo da class A { ... }
definição. Nem sequer é acessível a partir de uma extensão para o tipo (no Swift 3, consulte a segunda nota abaixo para alterações no Swift 4).
O bar
método file-private é acessível a partir do mesmo arquivo de origem.
Notas:
A proposta SE-0159 - Corrigir níveis de acesso privado sugeriu reverter para a semântica do Swift 2 no Swift 4. Após uma discussão longa e controversa na lista de discussão de evolução rápida, a proposta foi rejeitada .
A proposta SE-0169 - Melhorar a interação entre declarações e extensões privadas sugere tornar as private
declarações dentro de um tipo acessíveis a extensões do mesmo tipo se a extensão for definida no mesmo arquivo de origem.
Esta proposta foi aceita e implementada no Swift 4.
foo()
chamada.
Acabei de desenhar um diagrama sobre privado , privado de arquivo , aberto e público
Espero que possa ajudá-lo rapidamente, para obter uma descrição do texto, consulte a resposta de Martin R
[Atualização Swift 4]
fileprivate
não está ligada à extensão, mas para o arquivo (escrevendo uma extensão da classe A em outro arquivo não permitirá o uso de fileprivate
membros)
public
não permitirá que você herde, portanto, a terceira imagem está incorreta. Além disso, você sempre pode colocar uma extensão para qualquer classe, se puder vê-la. Explicar a visibilidade nas extensões não é uma boa ideia.
Uma regra prática é que você use private para variáveis, constantes, estruturas internas e classes que são usadas apenas dentro da declaração de sua classe / estrutura. Você usa fileprivate para itens que são usados dentro de suas extensões no mesmo arquivo que sua classe / estrutura, mas fora de seus chavetas de definição (por exemplo, seu escopo lexical).
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
}
}
No Swift 4.0, o Private agora está acessível em extensão, mas dentro do mesmo arquivo. Se você declarar / definir a extensão em outro arquivo, sua variável privada não estará acessível à sua extensão **
Arquivo Privado
O acesso privado a arquivos restringe o uso de uma entidade ao seu próprio arquivo de origem definidor. Use o acesso privado a arquivos para ocultar os detalhes de implementação de uma parte específica da funcionalidade quando esses detalhes forem usados em um arquivo inteiro.
Sintaxe: fileprivate <var type> <variable name>
Exemplo: fileprivate class SomeFilePrivateClass {}
Privado
O acesso privado restringe o uso de uma entidade à declaração anexa e às extensões dessa declaração que estão no mesmo arquivo . Use o acesso privado para ocultar os detalhes de implementação de uma parte específica da funcionalidade quando esses detalhes forem usados apenas em uma única declaração.
Sintaxe: private <var type> <variable name>
Exemplo: private class SomePrivateClass {}
Aqui estão mais detalhes sobre todos os níveis de acesso: Swift - Níveis de acesso
Veja estas imagens:
File: ViewController.swift
Aqui, a extensão e o controlador de exibição estão no mesmo arquivo, portanto, a variável privada pode testPrivateAccessLevel
ser acessada na extensão
Arquivo: TestFile.swift
Aqui, a extensão e o controlador de exibição estão em arquivos diferentes, portanto, a variável privada testPrivateAccessLevel
não está acessível na extensão.
Aqui a classe ViewController2
é uma subclasse de ViewController
e ambos estão no mesmo arquivo. Aqui, a variável privada testPrivateAccessLevel
não está acessível na subclasse, mas o fileprivate está acessível na subclasse.
Embora as respostas de @ MartinR e @ StephenChen sejam perfeitas, o Swift 4 muda as coisas um pouco.
Private agora é considerado privado para uma classe na qual é declarado e também para suas extensões.
O FilePrivate é considerado privado nesse arquivo, seja uma classe na qual a variável está definida, sua extensão ou qualquer outra classe definida no mesmo arquivo.
Atualizado para o Swift 5
Privado x FilePrivate
Para maior clareza, cole o snippet de código no 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
}
}
Nota : Fora do arquivo Swift, o private e o fileprivate não são acessíveis.
filePrivate - o nível do controlador de acesso está dentro do arquivo.
caso 1 : se criarmos extensão com o mesmo arquivo de classe e tentarmos acessar a função fileprivate ou a propriedade fileprivate em sua extensão - acesso permitido
caso 2 : se criarmos uma extensão de classe em novo arquivo - e agora tentarmos acessar a função fileprivate ou fileprivate propriedade - acesso não permitido
privado - o nível de controle de acesso está no escopo lexical
case 1 : Se propriedade ou função é declarada como privada na classe - então o escopo é por padrão a classe. caso 2 : se uma instância privada é declarada com no corpo da função - o escopo da instância é limitado ao corpo da função.
No exemplo a seguir, construções de linguagem modificadas por private
e fileprivate
parecem se comportar de forma idêntica:
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))
Isso está de acordo com a intuição, eu acho. Mas existe alguma exceção?
Atenciosamente.
Esta é a explicação para o swift 4. No swift 3, a diferença é o privado. O swift 3 private não pode ser acessado por sua extensão, apenas a própria classe A pode acessar.
Após o swift 4, o fileprivate se torna um pouco redundante, porque a pessoa normalmente não define a subclasse no mesmo arquivo. Privado deve ser suficiente para a maioria dos casos.
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()
}
}
Eu gosto disso porque é super simples para ivars.
Tente alterar o arquivo privado para privado (e vice-versa) e veja o que acontece na compilação ...
private
emfileprivate
. No entanto, se você tem o luxo de fazê-lo manualmente, pode se beneficiar de sairprivate
comoprivate
... se compilar, tudo de bom.