CodeGym /Blogue Java /Random-PT /Modificadores de acesso em Java
John Squirrels
Nível 41
San Francisco

Modificadores de acesso em Java

Publicado no grupo Random-PT
Oi! Na lição de hoje, conheceremos o conceito de modificadores de acesso e veremos exemplos de como trabalhar com eles. É claro que dizer 'conhecer' não é muito correto: você já está familiarizado com a maioria deles nas lições anteriores. Por via das dúvidas, vamos refrescar nossa memória do ponto mais importante. Os modificadores de acesso geralmente são palavras-chave que regulam o acesso a diferentes partes do seu código. Por que 'mais frequentemente'? Porque um deles é definido por padrão sem o uso de uma palavra-chave :) Java tem quatro modificadores de acesso. Nós os listamos em ordem do mais restritivo ao mais 'leniente':
  • privado;
  • padrão (pacote visível);
  • protegido;
  • público.
Vamos dar uma olhada em cada um deles e identificar quando eles podem ser úteis. E daremos exemplos :)

O modificador privado

Modificadores de acesso.  Privado, protegido, padrão, público - 2private é o modificador de acesso mais restritivo. Ele limita a visibilidade de dados e métodos dentro de uma única classe. Você conhece esse modificador da lição sobre getters e setters. Lembra deste exemplo?

public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Nós consideramos isso em uma lição anterior. Cometemos um erro grave aqui: tornamos nossos dados públicos, o que permitiu que outros programadores acessassem os campos diretamente e alterassem seus valores. Além do mais... esses valores foram atribuídos sem nenhuma verificação. Isso significa que nosso programa poderia criar um gato chamado "" com idade de -1.000 anos e peso 0. Para resolver esse problema, usamos getters e setters e também usamos o modificador private para limitar o acesso aos dados.

public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
Basicamente, limitar o acesso a campos e implementar getters e setters são os exemplos mais comuns de como a privacidadeseria usado em trabalho real. Em outras palavras, o objetivo principal desse modificador é obter o encapsulamento em um programa. A propósito, isso não se aplica apenas aos campos. Imagine que em seu programa tenha um método que implemente algumas funcionalidades MUITO complexas. O que podemos sugerir como exemplo? Digamos que seu método readDataFromCollider() aceite como entrada um endereço de dados, leia dados do Large Hadron Collider em formato de byte, converta esses dados em texto, grave-os em um arquivo e os imprima. Mesmo uma descrição do método parece assustadora, para não falar do código :) Para tornar o código mais legível, seria melhor não escrever toda a lógica complexa do método em um só lugar. Em vez disso, devemos separar a funcionalidade em métodos separados. Por exemplo, o readByteData()O método é responsável por ler os dados, o método convertBytesToSymbols() converte os dados lidos do colisor em texto, o método saveToFile() salva o texto recebido em um arquivo e o método printColliderData() imprime nosso arquivo de dados. No final, nosso método readDataFromCollider() será muito mais simples:

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
No entanto, como você deve se lembrar da lição sobre interfaces, o usuário só tem acesso à interface externa. E nossos 4 métodos não fazem parte disso. Eles são métodos auxiliares: nós os criamos para melhorar a legibilidade do código e não amontoar quatro tarefas diferentes em um método. Você não precisa dar ao usuário acesso a esses métodos. Se os usuários tiverem acesso ao método convertBytesToSymbols() ao trabalhar com o colisor, provavelmente ficarão confusos com o método e se perguntarão para que serve. Quais bytes são convertidos? De onde eles vieram? Por que convertê-los em texto? A lógica executada neste método não faz parte da interface exposta ao usuário. Apenas o readDataFromCollider()O método faz parte da interface. Então, o que fazemos com esses quatro métodos "internos"? Certo! Use o modificador privado para limitar o acesso a eles. Isso permite que eles realizem seu trabalho tranquilamente dentro da classe sem confundir o usuário, que não precisa conhecer a lógica de cada método individualmente.

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

O modificador protegido

O próximo modificador mais restritivo é protegido . Modificadores de acesso.  Privado, protegido, padrão, público - 3Os campos e métodos marcados pelo modificador de acesso protegido ficarão visíveis:
  • dentro de todas as aulas incluídas no mesmo pacote que o nosso;
  • dentro de todas as classes que herdam nossa classe.
A princípio, é difícil imaginar quando isso pode ser necessário. Não se surpreenda: há muito menos casos de uso para protected do que para private , e eles são muito específicos. Imagine que temos uma classe abstrata AbstractSecretAgent que representa um agente secreto em algum serviço de inteligência, bem como um pacote top_secret que contém essa classe e seus descendentes. Classes concretas como FBISecretAgent , MI6SecretAgent , MossadSecretAgent , etc. Dentro da classe abstrata, queremos implementar um contador de agente. Ele aumentará quando um novo agente for criado em algum lugar do programa. pacote top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Mas nossos agentes são secretos! Isso significa que eles e mais ninguém devem saber quantos deles existem. Podemos adicionar facilmente o modificador protegido ao campo agent_counter . Então instâncias de outras classes de agentes secretos e outras classes localizadas em nosso pacote top_secret podem obter seu valor.

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
E esse é o tipo de tarefa especializada que requer o modificador protegido :)

O modificador visível do pacote

O próximo na lista é o modificador padrão , também conhecido como modificador visível do pacote . Não é indicado por uma palavra-chave, pois Java o aplica por padrão a todos os campos e métodos. Se você escrever o seguinte em seu código:

int x = 10
a variável x terá acesso visível a este pacote . É fácil lembrar o que ele faz. Basicamente, padrão = herança protegida :) Como o modificador protegido , sua aplicação é limitada. Na maioria das vezes, o acesso padrão é usado em um pacote que possui algumas classes utilitárias que não implementam a funcionalidade de todas as outras classes do pacote. Vamos dar um exemplo. Imagine que temos um pacote de 'serviços'. Ele contém várias classes que trabalham com um banco de dados. Por exemplo, há uma classe UserService que lê os dados do usuário do banco de dados, uma classe CarServiceclasse que lê os dados do carro do mesmo banco de dados e outras classes, cada uma das quais trabalha com tipos específicos de objetos e lê os dados correspondentes do banco de dados.

package services;

public class UserService {
}

package services;

public class CarService {
}
Mas seria fácil para os dados no banco de dados estarem em um formato e precisarmos deles em outro. Imagine que as datas de nascimento dos usuários no banco de dados são armazenadas como <TIMESTAMP WITH TIME ZONE>...

2014-04-04 20:32:59.390583+02
...e, em vez disso, precisamos do objeto mais simples — um java.util.Date . Para resolver este problema, dentro do pacote services , podemos criar uma classe Mapper especial . Ele será responsável por converter os dados do banco de dados em nossos objetos Java familiares. Uma classe auxiliar simples. Geralmente declaramos todas as classes como classe pública ClassName , mas isso não é um requisito. Podemos declarar nossa classe auxiliar simplesmente como classe Mapper . Nesse caso, ele ainda faz seu trabalho, mas não é visível para ninguém fora do pacote de serviços !

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
E aqui está o raciocínio básico: por que alguém fora de um pacote precisa ver uma classe auxiliar que só funciona com as classes desse pacote?

O modificador público

E por último, mas não menos importante, o modificador público ! Você encontrou esse modificador em seu primeiro dia de estudo no CodeGym na primeira vez que executou public static void main(String[] args) . Modificadores de acesso.  Privado, protegido, padrão, público - 4Agora que você estudou a lição sobre interfaces, seu objetivo é óbvio para você :) Afinal, o modificador público foi criado para dar algo aos usuários. Por exemplo, a interface do seu programa. Suponha que você tenha escrito um programa tradutor que pode traduzir texto russo para inglês. Você criou um método translate(String textInRussian) que implementa toda a lógica necessária. Você marcou este método com a palavra public , e agora ele faz parte da interface:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
Você pode vincular este método ao botão 'Traduzir' na tela e pronto! Qualquer pessoa pode usá-lo. As partes do código marcadas com o modificador público destinam-se ao usuário final. Fornecendo um exemplo da vida real, privado é para todos os processos que ocorrem dentro de uma TV, mas público é para os botões do controle remoto usados ​​para gerenciar a TV. Além disso, o usuário não precisa saber como a televisão é construída ou como ela funciona. O controle remoto é o conjunto de métodos públicos : on() , off() , nextChannel() , PreviousChannel() , aumentoVolume() , diminuiçãoVolume() etc. Para reforçar o que você aprendeu, sugerimos que você assista a uma vídeo aula do nosso Curso de Java
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION