Exemplos Práticos de Encapsulamento

Encapsulamento é um dos pilares fundamentais da Programação Orientada a Objetos (POO). Em termos simples, encapsulamento significa esconder os dados internos de um objeto e permitir que ele seja manipulado apenas através de métodos definidos. Vamos explorar como aplicar encapsulamento em Python com alguns exemplos concretos.

Conceito de Encapsulamento

Para relembrar, encapsulamento permite proteger os dados de um objeto de acessos não autorizados e modificações indesejadas. Utilizamos modificadores de acesso como privado e protegido para controlar a visibilidade dos atributos e métodos.

Em Python, não temos modificadores de acesso explícitos como em outras linguagens (por exemplo, private, protected, public em Java). No entanto, utilizamos convenções de nomeação para indicar esses níveis de acesso:

  • Um atributo ou método _protegido é indicado com um único underscore (_) antes do nome.
  • Um atributo ou método __privado é indicado com dois underscores (__) antes do nome.

Exemplo Prático: Contador

Vamos criar uma classe Contador que encapsula o valor do contador e só permite modificá-lo através de métodos específicos.

class Contador:
    def __init__(self):
        self.__contador = 0  # Atributo privado

    def incrementar(self):
        self.__contador += 1

    def decrementar(self):
        if self.__contador > 0:
            self.__contador -= 1

    def obter_valor(self):
        return self.__contador

# Uso da classe Contador
meu_contador = Contador()
meu_contador.incrementar()
meu_contador.incrementar()
print(meu_contador.obter_valor())  # Saída: 2
meu_contador.decrementar()
print(meu_contador.obter_valor())  # Saída: 1

Neste exemplo, o atributo __contador é privado e só pode ser acedido e modificado através dos métodos incrementar, decrementar e obter_valor.

Exemplo Prático: Conta Bancária

Vamos desenvolver uma classe mais complexa que representa uma conta bancária, com métodos para depositar, levantar dinheiro e verificar o saldo.

class ContaBancaria:
    def __init__(self, titular, saldo_inicial=0):
        self.titular = titular
        self.__saldo = saldo_inicial  # Atributo privado

    def depositar(self, quantia):
        if quantia > 0:
            self.__saldo += quantia
        else:
            print("A quantia de depósito deve ser positiva.")

    def levantar(self, quantia):
        if 0 < quantia <= self.__saldo:
            self.__saldo -= quantia
        else:
            print("Levantamento inválido.")

    def obter_saldo(self):
        return self.__saldo

# Uso da classe ContaBancaria
minha_conta = ContaBancaria("João", 1000)
minha_conta.depositar(500)
print(minha_conta.obter_saldo())  # Saída: 1500
minha_conta.levantar(200)
print(minha_conta.obter_saldo())  # Saída: 1300

Neste exemplo, o saldo da conta (__saldo) é privado e só pode ser alterado utilizando os métodos públicos depositar e levantar.

Resumo

O encapsulamento é essencial para proteger os dados internos de um objeto de acessos e modificações indevidas. Utilizamos convenções de nomeação em Python para indicar atributos e métodos privados e protegidos. Ao aplicar encapsulamento, garantimos que as operações sobre os dados são realizadas de maneira controlada e segura.

Quiz

  1. O que é encapsulamento?

    • a) A capacidade de um objeto de herdar características de outro objeto.
    • b) Um modo de organizar o código em várias funções.
    • c) O processo de esconder os detalhes de implementação de um objeto e expor apenas uma interface pública.
    • d) Um sistema de bloquear código.
  2. Como indicamos um atributo privado em Python?

    • a) Adicionando um único underscore (_) antes do nome do atributo.
    • b) Adicionando um asterisco (*) antes do nome do atributo.
    • c) Adicionando dois underscores (__) antes do nome do atributo.
    • d) Adicionando um sinal de menos (-) antes do nome do atributo.
  3. Qual é a saída esperada do código seguinte?

    class Teste:
        def __init__(self):
            self.__valor = 5
    
        def obter_valor(self):
            return self.__valor
    
    obj = Teste()
    print(obj.obter_valor())
    
    • a) __valor
    • b) 5
    • c) None
    • d) erro
  4. É possível aceder diretamente a um atributo privado fora da classe que o define?

    • a) Sim
    • b) Não
    • c) Sim, mas apenas em classes derivadas
    • d) Sim, utilizando a notação self.__atributo
  5. Como podemos modificar o saldo de uma conta bancária encapsulada sem utilizar métodos públicos?

    • a) Modificando o atributo privado diretamente.
    • b) Utilizando métodos set e get adequados definidos na classe.
    • c) Não é possível.
    • d) A classe ContaBancaria precisa ser redefinida.

Respostas:

  1. c
  2. c
  3. b
  4. b
  5. b
<< Implementação do Encapsul... Índice Projeto Prático: Sistema... >>