O que é encapsulamento na Orientação a Objetos – Parte II

Por
Publicado em
3 min. de leitura

Fala, meus consagrados! Beleza?

Aqui no blog, temos a parte I sobre o encapsulamento. Relembrando, o encapsulamento é um dos pilares fundamentais da Programação Orientada a Objetos (POO). Ele está diretamente relacionado à ideia de proteger os dados internos de um objeto e controlar a forma como esses dados são acessados ou modificados.

Vamos continuar nosso estudo sobre encapsulamento!

O encapsulamento contribui para a construção de sistemas mais seguros, organizados, confiáveis e fáceis de manter. Ao esconder detalhes internos e expor apenas os métodos necessários, o encapsulamento reduz o acoplamento entre as classes e melhora a qualidade do projeto de software.

O encapsulamento torna o software mais seguro, organizado, confiável e fácil de manter.

Quando uma classe expõe diretamente seus atributos, qualquer outra parte do sistema pode modificar esses valores sem controle. Isso aumenta o risco de inconsistência nos dados.

Por exemplo, considere uma classe ContaBancaria:

public class ContaBancaria {
    public double saldo;
}

Como o atributo saldo está público, qualquer parte do sistema poderia fazer isto:

conta.saldo = -1000;

Isso é perigoso, pois uma conta bancária não deveria ter seu saldo alterado de qualquer maneira. O ideal é encapsular o atributo:

public class ContaBancaria {
    private double saldo;

    public void depositar(double valor) {
        if (valor > 0) {
            saldo += valor;
        }
    }

    public void sacar(double valor) {
        if (valor > 0 && valor <= saldo) {
            saldo -= valor;
        }
    }

    public double getSaldo() {
        return saldo;
    }
}

Agora, o saldo não pode ser alterado diretamente. Ele só pode ser modificado pelos métodos depositar() e sacar(), que possuem regras de validação.

Em Java, esse conceito é normalmente implementado por meio de atributos privados, métodos públicos, getters, setters e métodos privados auxiliares. Porém, é importante lembrar que encapsular não é apenas criar métodos get e set: é projetar a classe para proteger seu estado interno e oferecer uma interface clara, coerente e segura para os demais objetos do sistema.

Em Java, o encapsulamento é fortemente apoiado pelos modificadores de acesso. Eles definem o nível de visibilidade de atributos, métodos e classes.

Os principais modificadores são:

  • private: acesso permitido apenas dentro da própria classe
  • default: acesso permitido dentro do mesmo pacote
  • protected: acesso permitido no mesmo pacote e em subclasses
  • public: acesso permitido de qualquer lugar

Para aplicar o encapsulamento, é comum declarar os atributos como private e disponibilizar métodos públicos para acessá-los ou modificá-los.

Exemplo:

public class Produto {
    private String nome;
    private double preco;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public double getPreco() {
        return preco;
    }

    public void setPreco(double preco) {
        if (preco > 0) {
            this.preco = preco;
        }
    }
}

No exemplo, o atributo preco não pode receber qualquer valor. O método setPreco() valida se o valor é maior que zero antes de alterar o atributo.

Essa é uma das grandes vantagens do encapsulamento: controlar o acesso e proteger o estado interno do objeto.

Os métodos mais conhecidos associados ao encapsulamento são os getters e setters.

O arquivo-base explica que os métodos acessores, chamados de getters, são usados para recuperar o valor de um atributo privado. Já os métodos modificadores, chamados de setters, são usados para alterar o valor de um atributo privado.

Os métodos getters servem para consultar o valor de um atributo.

Exemplo:

public String getNome() {
    return this.nome;
}

Esse método retorna o valor armazenado no atributo nome.

Os métodos setters servem para alterar o valor de um atributo.

Exemplo:

public void setNome(String nome) {
    this.nome = nome;
}

Esse método recebe um valor por parâmetro e atribui esse valor ao atributo nome.

No entanto, um setter não precisa apenas atribuir um valor. Ele também pode validar regras de negócio:

public void setIdade(int idade) {
    if (idade >= 0) {
        this.idade = idade;
    }
}

Nesse caso, a idade só será alterada se o valor informado for maior ou igual a zero.

O encapsulamento não se aplica apenas aos atributos. Ele também pode ser aplicado aos métodos.

Uma classe pode possuir métodos privados que são usados apenas internamente. Esses métodos ajudam a organizar a lógica da classe, mas não precisam ser expostos para outras partes do sistema.

Exemplo:

public class Pedido {
    private double valorTotal;
    private double desconto;

    public double calcularValorFinal() {
        return valorTotal - calcularDesconto();
    }

    private double calcularDesconto() {
        return desconto;
    }
}

Nesse exemplo, o método calcularValorFinal() é público, pois representa uma operação que pode ser usada por outras classes.

Já o método calcularDesconto() é privado, pois representa um detalhe interno da implementação.

Essa prática evita que outras classes dependam de detalhes internos que podem mudar no futuro.

O encapsulamento traz diversos benefícios ao desenvolvimento de software.

  • Proteção dos dados: ao tornar os atributos privados, evita-se que eles sejam alterados indevidamente por outras classes;
  • Controle de acesso: a classe passa a controlar como seus dados podem ser consultados ou modificados;
  • Validação de regras de negócio: os métodos setters e outros métodos públicos podem validar dados antes de alterar o estado interno do objeto;
  • Facilidade de manutenção: como os detalhes internos ficam escondidos, a implementação pode ser alterada sem impactar diretamente o restante do sistema;
  • Redução do acoplamento:
    • Outras classes não precisam conhecer a estrutura interna do objeto;
    • Elas interagem apenas com os métodos públicos disponibilizados;
  • Organização do código: o encapsulamento ajuda a dividir o programa em partes menores, independentes e com responsabilidades bem definidas, conforme destacado no material-base. 

Abstração e encapsulamento são conceitos relacionados, mas não são sinônimos. A abstração se preocupa em representar apenas os aspectos essenciais de uma entidade do mundo real. O encapsulamento se preocupa em esconder os detalhes internos de implementação e controlar o acesso aos dados.

Por exemplo, uma classe Carro pode abstrair um veículo com os métodos ligar(), acelerar() e frear(). Internamente, ela pode encapsular atributos como velocidadeAtual, motorLigado e nivelCombustivel.

public class Carro {
    private boolean motorLigado;
    private int velocidadeAtual;

    public void ligar() {
        motorLigado = true;
    }

    public void acelerar() {
        if (motorLigado) {
            velocidadeAtual += 10;
        }
    }

    public int getVelocidadeAtual() {
        return velocidadeAtual;
    }
}

Quem usa a classe Carro não precisa saber exatamente como a velocidade é armazenada ou como o estado do motor é controlado. Basta utilizar os métodos públicos.

Espero que tenham gostado! 

Forte abraço e até a próxima jornada!


Professor Rogerão Araújo

Terças e quintas de TI. Conteúdo prático e artigos especializados para acelerar seu conhecimento. Acesse agora!

Por
Publicado em
3 min. de leitura