O encapsulamento é um dos conceitos fundamentais da programação orientada a objetos, que consiste em esconder a implementação interna de uma classe e fornecer uma interface externa para que outros objetos possam interagir com objetos desta classe de forma controlada.
O encapsulamento propõe programar em partes, o mais isolado possível, encapsulando-as. Este princípio ajuda a garantir a integridade dos dados e a modularidade do código em um sistema orientado a objetos.
O encapsulamento reforça a coesão da classe, tornando o software mais flexível, fácil de modificar e evoluir.
O encapsulamento é um conceito que está presente em diversos níveis em um projeto OO, porém, é popularmente utilizado para definir algumas práticas específicas na construção de uma classe.
O encapsulamento tem o objetivo de proteger o acesso indevido dos atributos e métodos de seus objetos.
Na prática, para haver encapsulamento as classes devem proteger as suas informações e comportamentos:
Devem possuir proteção no acesso a seus atributos e métodos;
Devem esconder os valores de seus atributos, deixando-os disponíveis/acessíveis apenas através de seus métodos.
Assim, um objeto de uma classe é uma entidade com fronteira e identidade bem definidas, que encapsulam o estado e comportamento.
Os objetos podem se comunicar entre si, mas em geral não sabem como outros objetos são implementados. Os detalhes de implementação permanecem ocultos dentro dos próprios objetos. Esse ocultamento de informações é crucial à boa engenharia de software.
Isso significa que um objeto deve ser responsável por seu próprio estado interno e oferecer métodos públicos para que outros objetos possam interagir com ele. Esses métodos podem ser usados para acessar ou modificar o estado interno do objeto, mas apenas dentro dos limites definidos por sua implementação.
Pensando no mundo real, os objetos também possuem essa proteção. (Ex.: interfaces de objetos reais: livro, fechadura etc)
O encapsulamento permite que o objeto tenha um controle mais preciso sobre seu próprio estado, tornando-o mais seguro e confiável.
Além disso, o encapsulamento permite que a implementação interna do objeto seja alterada sem afetar outros objetos que interagem com ele, desde que sua interface pública permaneça inalterada.
Para promover o encapsulamento, utiliza-se métodos get e set para todo atributo que precisa ser acessado externamente à classe. Estes métodos também podem ser usados internamente pela própria classe.
Define-se todo atributo com o modificador de acesso privado (private) - ou o mais privado possível considerando os objetivos do seu sistema.
Define-se todo método com o modificador de acesso adequado ao nível de acesso que desejamos.
Ou seja, os métodos devem ser públicos (public), quando deseja-se que todas as classes do sistema acessem os métodos;
Ou utiliza-se o modificador de acesso mais restritivo possível para a solução, quando desejamos que apenas algumas classes tenham acesso ao método. Ex.: Apenas classes do pacote; Apenas classes da hierarquia de herança.
Um método set é, geralmente, um método sem retorno (void) e com um ou mais parâmetros que alteram o valor de um ou mais atributos.
Um método get é, geralmente, um método sem parâmetros de entrada e com tipo de retorno definido que devolve o valor de determinado atributo.
💡 DICA: A maioria das IDEs tem opções para geração automática de métodos get e set nos moldes apresentados aqui a partir da seleção dos atributos desejados.
Arquivo Triangulo.java
public class Triangulo {
// Acesso de todos os atributos definidos como PRIVADO
private double area, base, altura;
// Métodos get e set definidos como PÚBLICOS
public double getAltura() {
return altura;
}
public void setAltura(double altura) {
this.altura = altura;
}
public double getBase() {
return base;
}
public void setBase(double base) {
this.base = base;
}
public double getArea() {
return area;
}
public void setArea(double area) {
this.area = area;
}
// Método para cálculo da área do triangulo via base e altura
public double calcularArea() {
if (base > 0 && altura > 0) {
area = base * altura / 2;
return area;
} else {
System.out.println("Os valores de base e altura devem ser maiores do que 0 para o cálculo da área do triângulo.");
return 0;
}
}
}
Arquivo Main.java
import java.util.Scanner;
class Main {
public static void main(String[] args) {
// Objetos Scanner para leitura de dados via teclado na console.
Scanner entradaDouble = new Scanner(System.in);
Scanner entradaString = new Scanner(System.in);
// Instância da classe Triangulo
Triangulo t = new Triangulo();
// Atributos para manipulação
String continua;
// Recebe dados para calcular a área de um triângulo enquanto ENTER for informado na console
do {
System.out.println("--CALCULADORA DE ÁREA DE UM TRIÂNGULO--");
System.out.println("Informe um valor de BASE para o triângulo:");
t.setBase(entradaDouble.nextDouble()); // Lê o próximo double digitado na console
System.out.println("Informe um valor de ALTURA para o triângulo:");
t.setAltura(entradaDouble.nextDouble()); // Lê o próximo double digitado na console
System.out.println("A área do triângulo informado é: " + Double.toString(t.calcularArea()));
System.out.println("Deseja continuar? Digite ENTER para calcular a área de mais um triângulo.");
continua = entradaString.nextLine(); // Lê a próxima string digitada na console
} while (continua.isEmpty());
// Fecha os scanners de teclado
entradaString.close();
entradaDouble.close();
}
}
Apesar do padrão ser gerar um método get e um método set para cada atributo de uma classe, seguindo os modelos de get e set apresentados nesta página, nem sempre isso é desejável.
Lembre-se: o encapsulamento consiste em proteger o acesso aos atributos e métodos dentro dos limites do seu sistema.
Assim, de acordo com as necessidades e objetivos do sistema:
Uma classe pode ter atributos sem acesso externo, pois este existe apenas para manipulação interna.
Um atributo pode não ter método set para que apenas a classe possa atualizar o valor do atributo ou para que o valor do atributo seja atualizado de forma implícita por outro(s) método(s).
Um atributo pode não ter método get para que apenas a classe possa conhecer o valor do atributo ou para que este seja usado de forma implícita por outro(s) método(s).
Um atributo pode ter a necessidade de mais de uma forma de método set quando atribuição de valor precisa ser feita de diferentes formas.
Um atributo pode ter a necessidade de mais de uma forma de método get quando deseja-se ao mesmo tempo fazer alguma outra manipulação, além do retorno do valor do atributo. Isto inclui até métodos get com parâmetros de entrada.