Métodos de Acesso (Getters e Setters)

Quando trabalhamos com classes em Python, frequentemente precisamos controlar como os atributos de uma instância são acedidos e modificados. Para isso, utilizamos métodos de acesso, conhecidos como getters e setters. Estes métodos permitem definir regras de acesso aos atributos e garantir a integridade dos dados. Vamos explorar como implementar esses métodos e entender a sua importância.

O Que São Getters e Setters?

Getters são métodos que permitem aceder ao valor de um atributo, enquanto setters são métodos que permitem modificar o valor de um atributo. Juntos, eles proporcionam uma interface controlada para atributos de uma classe, permitindo realizar validações e outras operações necessárias ao atualizar ou obter valores.

Implementação de Getters e Setters em Python

Embora Python não tenha uma sintaxe específica para getters e setters (como outras linguagens Orientadas a Objetos, como Java), ele fornece formas elegantes para implementá-los. A maneira mais comum de definir getters e setters em Python é utilizando decorators @property para getters e @<nome_do_atributo>.setter para setters. Vejamos um exemplo prático:

class ContaBancaria:
    def __init__(self, titular, saldo=0):
        self.__titular = titular
        self.__saldo = saldo

    @property
    def saldo(self):
        return self.__saldo

    @saldo.setter
    def saldo(self, valor):
        if valor >= 0:
            self.__saldo = valor
        else:
            raise ValueError("O saldo não pode ser negativo!")

    @property
    def titular(self):
        return self.__titular

# Criar instância da classe ContaBancaria
conta = ContaBancaria("João", 1000)

# Usar getter para aceder ao saldo
print(conta.saldo)  # Saída: 1000

# Usar setter para alterar o saldo
conta.saldo = 1500
print(conta.saldo)  # Saída: 1500

# Tentar definir um saldo negativo (causa ValueError)
try:
    conta.saldo = -500
except ValueError as e:
    print(e)  # Saída: O saldo não pode ser negativo!

Neste exemplo, saldo e titular são atributos privados (indicados por __ antes do nome do atributo). Usamos o decorator @property para definir o método getter saldo, e @saldo.setter para definir o método setter saldo. O setter inclui uma validação para garantir que o saldo não seja definido como negativo.

Vantagens dos Getters e Setters

  1. Encapsulamento: Permitindo controlar o acesso e a modificação dos atributos.
  2. Validação: Possibilitando adicionar validações ao definir ou obter valores.
  3. Flexibilidade: Facilitando a alteração da representação interna dos dados sem alterar a interface pública.

Exemplo do Mundo Real

Considere um sistema de gestão de inventário para uma loja. Cada produto pode ter um preço, e é vital garantir que esse preço nunca seja negativo. Utilizando getters e setters, podemos assegurar a integridade destes dados:

class Produto:
    def __init__(self, nome, preco):
        self.__nome = nome
        self.__preco = preco

    @property
    def preco(self):
        return self.__preco

    @preco.setter
    def preco(self, valor):
        if valor >= 0:
            self.__preco = valor
        else:
            raise ValueError("O preço não pode ser negativo!")

    @property
    def nome(self):
        return self.__nome

# Criar instância da classe Produto
produto = Produto("Computador", 1500)

# Usar getter para aceder ao preço
print(produto.preco)  # Saída: 1500

# Usar setter para alterar o preço
produto.preco = 2000
print(produto.preco)  # Saída: 2000

# Tentar definir um preço negativo (causa ValueError)
try:
    produto.preco = -100
except ValueError as e:
    print(e)  # Saída: O preço não pode ser negativo!

Resumo

Neste capítulo, aprendemos sobre o conceito de getters e setters, a sua importância na programação orientada a objetos e como implementá-los em Python. Utilizando decorators como @property e @<atributo>.setter, conseguimos garantir a integridade dos dados e aplicar validações necessárias.

Quiz

  1. Qual é a principal função dos métodos getters e setters?

    • a) Melhorar a performance
    • b) Controlar o acesso e a modificação dos atributos de uma classe
    • c) Aumentar a complexidade do código
    • d) Substituir o uso de atributos públicos
  2. Como se define um getter em Python?

    • a) Utilizando o decorator @property
    • b) Utilizando o decorator @getter
    • c) Utilizando a função def getter
    • d) Não é possível definir getters em Python
  3. O que acontece se tentarmos definir um atributo com um valor inválido num setter?

    • a) O valor é automaticamente corrigido
    • b) Uma exceção é lançada
    • c) O programa ignora o valor
    • d) O valor é aceite, mas não utilizado
<< Atributos de Instância vs... Índice Modificadores de Acesso (... >>