Capítulo 05: Programação Orientada a Objetos: Classes, Métodos, Encapsulamento e @property
Especialização em Sistemas com Python & POO com Type Hints • Capítulo 05
🗺️ Mapa Conceitual do Tópico
classDiagram
class ContaBancaria {
-str _numero_conta
-str _titular
-Decimal _saldo
+numero_conta: str
+titular: str
+saldo: Decimal
+depositar(valor) void
+sacar(valor) bool
+from_dict(dados)$ContaBancaria +validar_numero(numero)$ bool
}
note for ContaBancaria "Atributos privados encapsulados com @property
e métodos de fábrica (@classmethod)"
🏛️ 1. Paradigma Orientado a Objetos em Python
Uma classe em Python define um tipo de dado personalizado que agrupa estado (atributos) e comportamento (métodos).
Elementos Essenciais:
self: Referência explícita à instância atual invocada.__init__(): Método inicializador responsável por configurar os atributos de instância no Heap.@classmethod: Método vinculado à classe (recebecls), utilizado primariamente como Factory Method.@staticmethod: Método utilitário que não acessa estado de instância nem de classe.
🔒 2. Encapsulamento e @property
Em Python, a proteção de atributos segue as convenções PEP 8:
_atributo_protegido: Indica uso interno (convenção respeitada por IDEs e desenvolvedores).__atributo_privado: Aplica Name Mangling (_NomeClasse__atributo), dificultando o acesso externo acidental.@property: Permite expor métodos como atributos de leitura, enquanto@atributo.setteradiciona validações defensivas na escrita.
💻 Exemplo Prático e Tipado
"""
exemplo_05_classes_metodos_e_properties.py - Conta Bancária com Encapsulamento Estrito
"""
from decimal import Decimal
from typing import Self
class ContaBancaria:
"""Modela uma conta bancária corporativa com encapsulamento via @property."""
def __init__(self, numero_conta: str, titular: str, saldo_inicial: Decimal = Decimal("0.00")) -> None:
if not self.validar_numero(numero_conta):
raise ValueError(f"Número de conta '{numero_conta}' inválido. Deve ter formato XXXX-X.")
self._numero_conta: str = numero_conta
self._titular: str = titular.strip()
self._saldo: Decimal = Decimal("0.00")
if saldo_inicial > Decimal("0.00"):
self.depositar(saldo_inicial)
@property
def numero_conta(self) -> str:
return self._numero_conta
@property
def titular(self) -> str:
return self._titular
@property
def saldo(self) -> Decimal:
return self._saldo
def depositar(self, valor: Decimal) -> None:
if valor <= Decimal("0.00"):
raise ValueError("O valor de depósito deve ser positivo.")
self._saldo += valor
def sacar(self, valor: Decimal) -> bool:
if valor <= Decimal("0.00") or valor > self._saldo:
return False
self._saldo -= valor
return True
@classmethod
def from_dict(cls, dados: dict[str, str]) -> Self:
return cls(
numero_conta=dados["numero_conta"],
titular=dados["titular"],
saldo_inicial=Decimal(dados.get("saldo", "0.00")),
)
@staticmethod
def validar_numero(numero: str) -> bool:
partes = numero.split("-")
return len(partes) == 2 and partes[0].isdigit() and len(partes[0]) >= 4 and len(partes[1]) == 1
if __name__ == "__main__":
conta = ContaBancaria.from_dict({"numero_conta": "4455-8", "titular": "Rodrigo Prado", "saldo": "2500.00"})
print(f"Conta : {conta.numero_conta} | Titular: {conta.titular}")
print(f"Saldo : R${conta.saldo:,.2f}") conta.sacar(Decimal("500.00")) print(f"Pós-Saque: R$ {conta.saldo:,.2f}")
🔗 Recursos Pedagógicos do Capítulo 05
| Recurso Didático | Finalidade | Link de Acesso |
|---|---|---|
| 📊 Slides de Aula | Apresentação visual interativa com Dark Mode e suporte a teclado | Ver Slides |
| 🧠 Quiz Formativo | Teste interativo de fixação com feedback imediato por alternativa | Fazer Quiz |
| 💻 Exemplos de Código | Demonstrações funcionais com Type Hints e saída no console | Ver Exemplos |
| 🧩 Exercícios em 4 Níveis | Lista progressiva de fixação com gabarito em bloco colapsável | Resolver Exercícios |
| 🔢 Capítulo Anterior | 📚 Sumário de Tópicos | 📊 Próximo Capítulo |