Programação Swift 101 - Entendendo o Controle de Acesso

O Controle de Acesso é um dos recursos mais recentes adicionados à linguagem Swift. Ele permite que você especifique as partes do seu código que deseja tornar públicas e as partes que deseja ocultar. É uma ferramenta importante na criação de interfaces fáceis de usar e de entender.



Metas e Módulos

No Xcode, seus arquivos de código-fonte são atribuídos a diferentes destinos. Um projeto Xcode típico tem dois destinos - um para o arquivo principal do aplicativo e outro para testes de unidade. Para ver os destinos em um projeto, clique no primeiro nó no Project Navigator. Isso exibe o Editor de Projetos com uma lista de Projetos e Destinos à esquerda. (Se você não vir esta lista, clique no pequeno quadrado destacado em figura 1 ).

  Alvos
Figura 1 - Alvos do Xcode

Por padrão, todos os arquivos no Project Navigator e quaisquer novos arquivos adicionados ao projeto fazem parte do destino principal do aplicativo. O único arquivo que faz parte do destino do teste de unidade é o arquivo de código de teste de unidade no grupo 'Testes'.

Para ver a qual destino um determinado arquivo pertence, selecione-o no Project Navigator, vá para o File Inspector e procure na seção Target Membership ( Figura 2 ).

  Associação alvo
Figura 2 - Visualizando a associação de destino de um arquivo

Por padrão, todo o código em um projeto pertencente ao mesmo destino também faz parte de um único módulo. No Swift, por padrão, todo o código que faz parte de um mesmo módulo pode acessar todos os outros códigos desse módulo. Esta é uma grande melhoria em relação ao Objective-C, onde você só poderia fazer referência a outra classe no mesmo projeto importando seu arquivo de cabeçalho - uma verdadeira lombada ao ensinar iniciantes a escrever código.

Se você estiver criando um aplicativo único e autônomo, esse nível de controle de acesso pode funcionar bem para a maior parte do código que você escreve. No entanto, normalmente há vários lugares em que é melhor alterar esse nível de acesso padrão.

Níveis de acesso

Existem três níveis de acesso no Swift ( Figura 3 ).

  Níveis de acesso
Figura 3 - Níveis de acesso ao código do Swift
  1. Público - Permite o acesso ao código dentro do mesmo módulo, ou a outro módulo que importa o módulo no qual o código está declarado.
  1. interno - Permite o acesso ao código no mesmo módulo, mas não a qualquer outro módulo. Este é o nível de acesso padrão do Swift.
  1. Privado - Restringe o acesso ao arquivo fonte no qual o código é declarado. Embora seja comum ter uma única classe, estrutura, enumeração, etc. definidos em um arquivo de código fonte, você pode declarar mais de um por arquivo.

Modificadores de controle de acesso

Você usa os modificadores public, internal e private para especificar o nível de acesso do seu código. Por exemplo, aqui estão os modificadores usados ​​para declarar o acesso às classes:

Aqui estão os modificadores usados ​​para declarar acesso aos membros de uma classe:

Novamente, se você não especificar um modificador de acesso, o nível de acesso padrão para seu código é interno .

Nível de acesso à classe

Vamos dar uma olhada prática no nível de acesso da classe. Para trabalhar com essas etapas, baixe o projeto de amostra em esse link .

  1. Abra o AccessControlDemo projeto localizado na pasta onde você baixou o projeto de amostra.
  1. Como mostra o Project Navigator, existem três classes que você usará para verificar como os níveis de acesso funcionam com as classes; Nota pública , Nota interna , e Nota Privada ( Figura 4 ).
  Aulas de nível de acesso
Figura 4 - As classes de demonstração do 'nível de acesso à classe'
  1. Se você selecionar cada uma das três classes, verá as seguintes declarações de classe:

Mantenha os três níveis de acesso diferentes descritos em Figura 3 em mente enquanto tentamos acessar essas classes de lugares diferentes:

  • Um módulo diferente
  • O mesmo módulo
  • O mesmo arquivo de código-fonte

Acessando uma classe pública

Vamos começar tentando acessar o público classe de um módulo diferente.

  1. No Project Navigator, expanda o AccessControlDemoTests pasta do grupo e selecione a AccessControlDemoTests.swift arquivo de código.
  1. Adicione o seguinte código ao testeExemplo método:

  1. Imprensa Comando+B para construir o projeto. Você vai obter um Uso de identificador não resolvido 'PublicNote' erro do compilador. Você sabe por quê?

Lembre o Nota pública class está em um módulo diferente daquele em que a classe de teste de unidade está, então precisamos importar o módulo.

  1. Por padrão, o nome do módulo de um projeto é o mesmo que o nome do projeto, então você precisa adicionar a instrução de importação no topo do AccessControlDemoTests arquivo de código:

  1. Imprensa Comando+B para construir o projeto e o erro do compilador desaparecerá.
  1. Agora adicione o seguinte código ao testeExemplo método:

  1. Imprensa Comando+B e ambas as linhas de código produzem um Uso de identificador não resolvido erro. Isso porque, como Figura 3 shows, você não pode acessar uma classe interna ou privada de um módulo diferente.
  1. Vá em frente e exclua as duas últimas linhas de código que você adicionou na etapa anterior para que o projeto seja compilado sem erros.

Agora vamos ver como isso funciona quando tentamos no mesmo módulo onde as classes são declaradas.

  1. Selecione os ViewController.swift arquivo no Project Navigator.
  1. No viewDidLoad método, adicione as três linhas de código a seguir:

As duas primeiras linhas de código funcionam muito bem. Isso porque você pode fazer referência a um público ou interno class do código no mesmo módulo. No entanto, a última linha de código falha, porque você só pode referenciar um privado class de dentro do mesmo arquivo de código-fonte onde o privado classe é declarada.

  1. Exclua a última linha de código que você adicionou na etapa anterior, para que o projeto seja compilado sem erros.
  1. Selecione os PrivateNote.swift no Project Navigator e adicione a seguinte declaração de classe ao arquivo de código:

Este código compila sem erro. Isso porque a única maneira de acessar uma classe privada é a partir do código que reside no mesmo arquivo de código-fonte.

Nível de acesso do membro da classe

Agora vamos ver como os diferentes níveis de acesso funcionam com membros de uma classe.

  1. Selecione os Nota.rápido arquivo no Project Navigator. Aqui está a definição de classe que você encontrará lá:

Isto é um público classe nomeada Observação isso tem público , interno , e privado métodos. Vamos tentar acessar os métodos desta classe de um módulo diferente.

  1. Selecione os AccessControlDemoTests.swift arquivo no Project Navigator e adicione o seguinte código ao testeExemplo método. Este código cria uma instância do Observação classe:

  1. Adicione uma nova linha de código vazia e digite n. como em Figura 5 .

Observe que o único método acessível de outro módulo é o público método.

  1. Exclua os últimos caracteres inseridos na etapa anterior.

Vamos ver como funcionam os níveis de acesso ao método quando os acessamos de dentro do mesmo módulo.

  1. Selecione os ViewController.swift arquivo no Project Navigator e adicione o seguinte código ao viewDidLoad método:

  1. Adicione uma nova linha de código vazia e digite n. como em Figura 6 .

Observe que tanto o público e interno métodos são acessíveis a partir do código localizado no mesmo módulo.

  1. Exclua os últimos caracteres inseridos para que o projeto seja compilado novamente sem erros.

Agora vamos ver como os níveis de acesso ao método funcionam quando os acessamos de dentro do mesmo arquivo de código-fonte.

  1. Selecione os Nota.rápido arquivo de código no Project Navigator.
  1. Adicione a seguinte declaração de classe na parte inferior do Nota.rápido arquivo de código:

  1. Em uma nova linha vazia, digite n. e você verá todos os três métodos, incluindo o método marcado como privado em Figura 7 .
  métodos públicos, internos e privados
Figura 7 - Todos os três métodos aparecem no Code Completion.
  1. Remova os últimos caracteres que você digitou para que o projeto seja compilado novamente.
  1. Observe que você também pode acessar o método privado dentro da classe em que está declarado. Por exemplo, se você for para o getPublicNote método e tipo auto. você pode ver que todos os três métodos são acessíveis ( Figura 8 ).
  acessar privado de dentro da classe
Figura 8 - Você pode acessar um membro privado de dentro da classe em que está declarado.
  1. Se você digitou auto. no getPublicNote método, exclua-o para que o projeto seja compilado sem erros.

Tipos, membros e níveis de acesso

Aqui estão algumas regras básicas que governam como definir o nível de acesso de uma classe afeta o nível de acesso de seus membros (propriedades, métodos, inicializadores e subscritos).

  • Definir o nível de acesso de uma classe para privado define todos os seus membros para privado por padrão.
  • Definir o nível de acesso de uma classe para público ou interno (ou não especifique nenhum nível, cujo padrão é interno ), padroniza todos os seus membros para interno .

Desenvolvedores iniciantes geralmente cometem o erro de fazer com que todos os membros de uma classe público . Essa não é uma boa abordagem, porque expõe membros da classe que podem não ser úteis para um consumidor da classe e, no processo, atrapalha e confunde a interface da classe.

Além disso, se você expor muito do funcionamento interno de uma classe, corre o risco de permitir que os desenvolvedores usem sua classe de maneiras inseguras e que produzem acoplamento rígido. Se as classes estiverem muito fortemente acopladas, isso cria uma base de código frágil – quando uma classe muda, cria uma reação em cadeia que força grandes mudanças em outras classes.

Assim, a abordagem da Apple de tornar os membros de uma público classe interno por padrão é o caminho certo a seguir. Isso força você a dar o passo extra de adicionar o público palavra-chave para um membro, fazendo com que você considere se esse membro deve ser público .

Nível de acesso a métodos e funções

Além do nível de acesso padrão que recebe de sua classe que o contém, o nível de acesso de um método deve ser definido para o acesso mais restritivo de seus parâmetros e valores de retorno. Por exemplo:

Este método tem um privado tipo de parâmetro e um interno tipo de retorno. Isso torna todo o método privado e, portanto, deve ser marcado privado como mostra este exemplo de código.

Essa regra também se aplica a funções, que não possuem uma classe de contenção.

Nível de acesso do inicializador

As regras que se aplicam ao nível de acesso padrão de um método que ele recebe de sua classe que o contém também se aplicam aos inicializadores— público e interno as aulas têm interno inicializadores e privado as aulas têm privado inicializadores por padrão.

Onde essa regra geralmente surpreende os desenvolvedores é quando eles percebem que precisam criar um público inicializador de um público classe, já que seu padrão é interno .

As regras que se aplicam aos parâmetros de método também se aplicam aos inicializadores — seu nível de acesso deve ser definido para o nível de acesso mais restritivo de seus parâmetros.

Você pode especificar manualmente o acesso de um inicializador para ser igual ou igual ao nível de acesso de sua classe que o contém. A única exceção é inicializadores necessários , que devem ter o mesmo nível de acesso que o tipo em que estão contidos.

O inicializador para estruturas é interno por padrão, a menos que tenha algum privado membros. Nesse caso, seria privado por padrão. Você também pode criar manualmente um público inicializador para uma estrutura.

Níveis de Acesso Variável, Constante, Propriedade e Subscrito

No Swift, você não pode definir um nível de acesso variável, constante, propriedade ou subscrito superior ao nível de seu tipo.

Por exemplo, no código a seguir, você deve declarar o Nota propriedade como privado , porque seu tipo, Nota Privada é privado :

Níveis de Acesso Getter e Setter

Os métodos getter e setter são atribuídos automaticamente ao mesmo nível de acesso que a variável, constante, propriedade ou subscrito a que pertencem.

Você pode especificar manualmente um nível de acesso mais baixo para um setter do que um getter para restringir a acessibilidade de leitura e gravação desse membro. Para fazer isso, especifique privado(conjunto) ou interno (conjunto) antes de o foi ou subscrito declaração. Por exemplo:

Observe que isso funciona para propriedades computadas e armazenadas, pois o Swift gera um getter e um setter para uma propriedade armazenada nos bastidores.

Níveis de acesso diversos

Existem outras regras de acesso que se aplicam a enumerações, protocolos, extensões, genéricos, tuplas, tipos aninhados e aliases de tipo. Consulte a documentação da Apple para descobrir as regras especiais que se aplicam a cada um.

Herança e Controle de Acesso

Um dos efeitos mais interessantes do controle de acesso é como ele funciona com herança.

Herança e classes

Você pode subclassificar qualquer classe à qual seu código tenha acesso. Isso significa:

  • Você pode criar uma subclasse de um público aula de qualquer lugar.
  • Você pode criar uma subclasse de uma classe interna somente de dentro do mesmo módulo.
  • Você pode criar uma subclasse de um privado class apenas de dentro do mesmo arquivo de código-fonte.

Uma classe não herda automaticamente seu nível de acesso de superclasse. Por exemplo, no código a seguir, Nota SubPública não herda sua superclasse público nível de acesso:

Se você quiser Nota SubPública ser público , você precisa declará-lo explicitamente. No entanto, observe que você não pode especificar um nível de acesso para uma subclasse superior à sua superclasse. Então, por exemplo, você não pode subclassificar um interno aula e faça público .

Herança e Membros de Classe

Os membros da classe também não herdam automaticamente seu nível de acesso. Em vez disso, eles obtêm seu nível de acesso padrão com base no nível de acesso da classe em que são declarados, conforme descrito anteriormente no Níveis de acesso dos tipos e seus membros seção.

Por exemplo, no código a seguir, Subnota é uma subclasse de Observação , e substitui sua getPublicNote método. Este método é interno por padrão. Isso porque ele não obtém seu acesso padrão de sua superclasse, mas sim da classe em que está declarado.

Ao substituir um membro, você pode torná-lo mais acessível na subclasse, mas não pode torná-lo menos acessível. Por exemplo, no código a seguir Subnota é uma subclasse de Observação . Ele sobrepõe o getPrivateNote método e eleva seu nível de acesso para público :

Conclusão

O controle de acesso é um recurso importante do Swift que deve ser aplicado com cuidado às suas classes iOS. Vale a pena dedicar um tempo para criar uma API que contenha apenas os membros necessários, porque facilita a criação e extensão de seus aplicativos no futuro!