Programação orientada a objetos em Python
A POO organiza o programa em objetos que possuem estado e oferecem comportamento por interfaces claras.
O que é programação orientada a objetos em Python?
A POO modela um sistema como objetos colaboradores. Cada objeto combina estado e operações válidas, tornando responsabilidades mais claras em aplicações grandes.
Os quatro princípios fundamentais
- Encapsulamento: reunir estado e comportamento e controlar o acesso.
- Abstração: expor uma interface útil e ocultar detalhes desnecessários.
- Herança: especializar uma classe apenas quando existe uma verdadeira relação é-um.
- Polimorfismo: usar a mesma operação com objetos distintos e comportamento adequado.
Como o exemplo foi projetado
- BankAccount possui o saldo e valida depósitos.
- SavingsAccount reutiliza o contrato base.
- SavingsAccount sobrescreve month_end para aplicar juros.
- O laço usa todas as contas pela mesma interface.
Exemplo básico
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = float(balance)
@property
def balance(self):
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self._balance += amount
def month_end(self):
return "No interest"
class SavingsAccount(BankAccount):
def __init__(self, owner, balance, interest_rate):
super().__init__(owner, balance)
self.interest_rate = interest_rate
def month_end(self):
self._balance *= 1 + self.interest_rate
return "Interest applied"
accounts = [
BankAccount("Ada", 100),
SavingsAccount("Lin", 200, 0.05),
]
accounts[0].deposit(50)
for account in accounts:
status = account.month_end()
print(f"{account.owner}: {account.balance:.2f} ({status})")
Saída esperada
Ada: 150.00 (No interest)
Lin: 210.00 (Interest applied)
Os quatro princípios de POO na prática
Estes exemplos mostram como Python aplica encapsulamento, abstração, herança e polimorfismo no código cotidiano.
Encapsulamento
reunir estado e comportamento e controlar o acesso.
class BankAccount:
def __init__(self, balance=0):
# Double underscores prevent accidental direct access.
self.__balance = balance
@property
def balance(self):
# Expose read access without exposing mutation.
return self.__balance
def deposit(self, amount):
# Keep validation next to the state it protects.
if amount <= 0:
raise ValueError("Amount must be positive")
self.__balance += amount
account = BankAccount(100)
account.deposit(50)
print(account.balance) # 150
Abstração
expor uma interface útil e ocultar detalhes desnecessários.
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
# Callers know what pay does, not how each provider does it.
pass
class CreditCard(PaymentMethod):
def pay(self, amount):
# The concrete class hides its payment implementation.
return f"Paid ${amount:.2f} by card"
payment = CreditCard()
print(payment.pay(25))
Herança
especializar uma classe apenas quando existe uma verdadeira relação é-um.
class Employee:
def __init__(self, name):
self.name = name
def describe(self):
return self.name
class Developer(Employee):
def __init__(self, name, language):
# Reuse initialization from the parent class.
super().__init__(name)
self.language = language
def describe(self):
# Extend inherited behavior instead of duplicating it.
return f"{super().describe()} writes {self.language}"
print(Developer("Ada", "Python").describe())
Polimorfismo
usar a mesma operação com objetos distintos e comportamento adequado.
class EmailNotification:
def send(self, message):
return f"Email: {message}"
class SmsNotification:
def send(self, message):
return f"SMS: {message}"
def notify(channels, message):
for channel in channels:
# The same call selects behavior from each concrete object.
print(channel.send(message))
channels = [EmailNotification(), SmsNotification()]
notify(channels, "Order shipped")
Como funciona
BankAccount encapsula o saldo. SavingsAccount herda a interface e sobrescreve month_end. O laço trata ambos uniformemente e Python seleciona o método em tempo de execução.
Altere os valores e execute o programa no compilador Python online CodeUtility sem instalar Python.
Exercícios práticos
Altere as entradas e teste casos de borda antes de usar conjuntos de dados maiores.
- Preveja a saída antes de executar.
- Trate entradas vazias ou inválidas.
- Extraia a lógica para uma função e adicione testes.