O que é um bom exemplo para diferenciar entre fileprivate e private no Swift3
142
Este artigo foi útil para entender os novos especificadores de acesso em Swift 3. Também fornece alguns exemplos de diferentes usos de fileprivatee private.
Minha pergunta é - não está usando fileprivateuma função que será usada apenas neste arquivo o mesmo que usar private?
fileprivateagora é o que privatecostumava ser nas versões anteriores do Swift: acessíveis a partir do mesmo arquivo de origem. Uma declaração marcada como privateagora 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 {privatefunc foo(){}fileprivatefunc 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 levela.bar()
O foomé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 barmé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.
Se você está convertendo código automaticamente a partir Swift 2-3, Xcode vai se transformar privateem fileprivate. No entanto, se você tem o luxo de fazê-lo manualmente, pode se beneficiar de sair privatecomo private... se compilar, tudo de bom.
Dan Rosenstark 14/03
@DanielLarsson: Re suas sugestões de edição: Ambos os comentários se aplicam à foo()chamada.
Martin R
82
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
cuidado, fileprivatenã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 fileprivatemembros)
Vince
1
Isso parece incorreto. Você está perdendo o ponto principal. Você precisa diferenciar as classes que estão dentro do mesmo módulo e que estão em módulos diferentes. Se eles estiverem em módulos diferentes, publicnã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.
Sulthan
Na verdade, devo mencionar que meu diagrama funciona apenas no mesmo módulo, portanto, na terceira imagem, eu só quero que o usuário entenda rapidamente o fileprivate só funciona no mesmo arquivo.
Stephen Chen
6
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).
classViewController:UIViewController{@IBOutletvar tableView:UITableView!//This is not used outside of class Viewcontrollerprivatevar titleText ="Demo"//This gets used in the extensionfileprivatevar list =[String]()overridefunc viewDidLoad(){
navigationItem.title = titleText}}extensionViewController: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 {}
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 testPrivateAccessLevelser 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 testPrivateAccessLevelnão está acessível na extensão.
Aqui a classe ViewController2é uma subclasse de ViewControllere ambos estão no mesmo arquivo. Aqui, a variável privada testPrivateAccessLevelnã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.
Para maior clareza, cole o snippet de código no Playground
classSum1{let a:Int!let b:Int!privatevar result:Int?fileprivatevar 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
extensionSum1{func testing(){// Both private and fileprivate accessible in extensions
print(result)
print(resultt)}}//If SUM2 class is created in same file as Sum1 ---
classSum2{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.
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.
private
emfileprivate
. No entanto, se você tem o luxo de fazê-lo manualmente, pode se beneficiar de sairprivate
comoprivate
... se compilar, tudo de bom.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]
fonte
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 defileprivate
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).
fonte
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ãoArquivo: 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 deViewController
e ambos estão no mesmo arquivo. Aqui, a variável privadatestPrivateAccessLevel
não está acessível na subclasse, mas o fileprivate está acessível na subclasse.fonte
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.
fonte
Atualizado para o Swift 5
Privado x FilePrivate
Para maior clareza, cole o snippet de código no Playground
Nota : Fora do arquivo Swift, o private e o fileprivate não são acessíveis.
fonte
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.
fonte
No exemplo a seguir, construções de linguagem modificadas por
private
efileprivate
parecem se comportar de forma idêntica:Isso está de acordo com a intuição, eu acho. Mas existe alguma exceção?
Atenciosamente.
fonte
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.
fonte
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 ...
fonte