JavaRush /Blogue Java /Random-PT /Getters e setters

Getters e setters

Publicado no grupo Random-PT
Olá! Nas palestras anteriores você já aprendeu como criar suas próprias classes completas, com campos e métodos. Este é um progresso sério, muito bem! Mas agora tenho que lhe contar uma verdade desagradável. Não criamos nossas aulas muito bem! Por que? À primeira vista, não há erros nesta classe:
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!");
   }
}
Na verdade, existe. Imagine que enquanto está sentado no trabalho você escreveu uma classe como esta Cat, denotando gatos. E ele foi para casa. Enquanto você estava fora, outro programador veio trabalhar, criou sua própria classe Main, onde começou a usar a classe que você escreveu Cat.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Não importa por que ele fez isso ou como aconteceu: talvez a pessoa estivesse cansada ou não dormisse o suficiente. Outra coisa é importante: nossa classe atual Catpermite atribuir valores malucos aos campos. Como resultado, o programa contém objetos com estado incorreto, como este gato com idade de -1000 anos. Que erro acabamos cometendo? Quando criamos a classe, expomos seus dados. Campos namee agesão weightde domínio público. Eles podem ser acessados ​​em qualquer lugar do programa: basta criar um objeto Cat– e pronto, qualquer programador tem acesso aos seus dados diretamente através do operador “ .
Cat cat = new Cat();
cat.name = "";
Aqui acessamos diretamente o campo namee definimos seu valor. Precisamos proteger de alguma forma nossos dados contra interferências externas incorretas. O que é necessário para isso? Primeiro, todas as variáveis ​​de instância (campos) devem ser marcadas com um modificador private. Private é o modificador de acesso mais estrito em Java. Se você usá-lo, os campos da classe Catnão estarão acessíveis fora dela.
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 class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//error! The name field in the Cat class has private access!
   }
}
O compilador vê isso e imediatamente produz um erro. Agora os campos parecem estar protegidos. Mas acontece que o acesso a eles está “hermeticamente” fechado: o programa não consegue nem pesar o peso de um gato existente, se necessário. Isso também não é uma opção: dessa forma nossa classe é praticamente impossível de usar. Idealmente, precisamos permitir algum tipo de acesso limitado aos dados:
  • Outros programadores deveriam ser capazes de criar objetosCat
  • Eles devem ser capazes de ler dados de objetos já existentes (por exemplo, obter o nome ou a idade de um gato já existente).
  • Também deve ser possível atribuir valores de campo. Mas ao mesmo tempo - apenas valores corretos. Nossos objetos devem ser protegidos de itens incorretos (sem “idade = -1000 anos” e similares).
A lista de requisitos é decente! Mas, na verdade, tudo isso é facilmente alcançado usando métodos especiais - getters e setters .
Getters e setters - 2
O nome vem do inglês “ get ” - “ receber ” (ou seja, “método para obter o valor de um campo”) e set - “ set ” (ou seja, “método para definir o valor de um campo”). Vamos ver como eles ficam usando nossa classe como exemplo Cat:
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) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       this.weight = weight;
   }
}
Como você pode ver, tudo é bem simples :) Seus nomes geralmente consistem na palavra get/set + o nome do campo pelo qual são responsáveis. Por exemplo, um método getWeight()retorna o valor de um campo weightpara o objeto para o qual foi chamado. Isto é o que parece no programa:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       String barsikName = barsik.getName();
       int barsikAge = barsik.getAge();
       int barsikWeight = barsik.getWeight();

       System.out.println("Cat name: " + barsikName);
       System.out.println("Cat's age: " + barsikAge);
       System.out.println("Weight of the cat: " + barsikWeight);
   }
}
Saída do console:

Name кота: Барсик
Возраст кота: 5
Вес кота: 4
Agora de outra classe( Main) há acesso aos campos Cat, mas apenas através de getters . Observe que os getters possuem um modificador de acesso public, o que significa que podem ser acessados ​​de qualquer lugar do programa. E quanto à atribuição de valores? Os métodos setter são responsáveis ​​por isso
public void setName(String name) {
   this.name = name;
}
O trabalho deles, como você pode ver, também é simples. Chamamos um método setName()em um objeto Cat, passamos uma string como argumento e essa string é atribuída a um campo namedo nosso objeto.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);

       System.out.println("The original name of the cat is " + barsik.getName());
       barsik.setName("Basil");
       System.out.println("The new name of the cat -" + barsik.getName());
   }
}
Aqui usamos getters e setters. Primeiro, usando um getter, recebemos e enviamos para o console o nome inicial do gato. Então, usando um setter, nameum novo valor foi atribuído ao seu campo - “Vasily”. E então, usando um getter, pegamos o nome novamente para verificar se realmente mudou. Saída do console:

Изначальное Name кота — Барсик
Новое Name кота — Васorй
Ao que parece, qual é a diferença? Também podemos atribuir valores incorretos aos campos dos objetos, mesmo que tenhamos setters:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
Saída do console:

Возраст Барсика — -1000 лет
A diferença é que um setter é um método completo . E em um método, diferentemente de um campo, você pode incluir a lógica de verificação necessária para evitar valores inaceitáveis. Por exemplo, você pode facilmente desativar a atribuição de um número negativo como idade:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age cannot be negative!");
   }
}
E agora nosso código funciona corretamente!
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
Saída do console:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
Existe uma restrição dentro do setter e ela protege contra tentativas de configuração de dados incorretos. A idade de Barsik permaneceu inalterada. Getters e setters sempre devem ser criados. Mesmo que seus campos não tenham restrições de valores possíveis, não haverá nenhum dano com eles. Imagine uma situação: você e seus colegas estão escrevendo um programa juntos. Você criou uma classe Catcom campos públicos e todos os programadores os utilizam como desejam. E então, um belo dia, você percebe: “Droga, mais cedo ou mais tarde alguém pode acidentalmente atribuir um número negativo a uma variável weight! Precisamos criar setters e tornar todos os campos privados!” Você os cria e todo o código escrito por seus colegas quebra instantaneamente. Afinal, eles já haviam escrito um monte de código onde acessavam os campos Catdiretamente.
cat.name = "Hippopotamus";
E agora os campos se tornaram privados e o compilador produz vários erros!
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
Em tal situação, seria melhor ocultar os campos e criar getter-setters desde o início . Todos os seus colegas os usariam e, se você percebesse tarde que precisava limitar os valores dos campos, bastaria adicionar uma verificação dentro do setter. E ninguém quebraria o código já escrito. Claro, se quiser acesso somente leitura a um determinado campo, você pode criar um getter para ele. “Fora”, ou seja, fora da sua classe, apenas métodos deverão estar disponíveis. Os dados devem estar ocultos.
Getters e setters - 4
Uma analogia pode ser feita com um telefone celular. Imagine que em vez de um celular normal ligado, você recebeu um telefone com a caixa aberta, onde estão todos os fios, circuitos, etc. saindo. O telefone funciona: se você se esforçar e mexer nos diagramas, poderá até conseguir fazer uma ligação. Mas você provavelmente vai quebrá-lo. Em vez disso, a empresa fabricante oferece uma interface: o cliente simplesmente disca os números necessários, pressiona o botão verde do aparelho e a chamada começa. E ele não se importa com o que está acontecendo lá dentro com os circuitos e fios e como eles realizam sua tarefa. Neste exemplo, a empresa limitou o acesso aos “interiores” (dados) do telefone e deixou apenas a interface (métodos) de fora. Como resultado, o cliente conseguirá o que deseja (fazer uma ligação) e definitivamente não quebrará nada por dentro.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION