Fundamentos da Programação Orientada a Objetos em Python

Em desenvolvimento de software, a estruturação de informações segue um processo sistemático. Inicialmente, definimos uma estrutura abstrata denominada classe, que serve como modelo para entidades do domínio. Em seguida, ao instanciar essa classe, criamos um objeto concreto na memória. Por último, preenchemos as características específicas desse objeto através de atribuição de propriedades.

Definição de Métodos de Instância

A sintaxe para declarar métodos em classes é similar à definição de funções convencionais, com uma distinção crucial: a presença do parâmetro especial self. Esse parâmetro é obrigatório em todos os métodos de classe e referencia a própria instância que está executando o método. Quando um método é invocado por um objeto, o interpretador Python automaticamente passa a instância como primeiro argumento para self. Para acessar atributos ou outros métodos da mesma instância dentro do corpo do método, a utilização de self é indispensável. Vale notar que, durante a chamada do método, o argumento correspondente a self não é explicitamente fornecido pelo desenvolvedor.

Método Construtor

As classes em Python podem implementar um método especial chamado __init__, conhecido como construtor. Esse método é executado automaticamente no momento da instanciação da classe, permitindo a inicialização de atriubtos e a realização de configurações iniciais. Os argumentos fornecidos durante a criação do objeto são encaminhados diretamente para os parâmetros do método __init__.

Métodos Especiais (Mágicos)

Python oferece diversos métodos especiais que permitem customizar o comportamento dos objetos em operações específicas. Por exemplo, o método __str__ controla a representação textual de um objeto, similar ao método toString() em Java. Para comparações, podemos implementar métodos como __lt__ (para operadores de menor que) e __eq__ (para igualdade). Esses métodos são invocados implicitamente ao utilizar os operadores correspondentes.


class Produto:
    def __init__(self, codigo: int, descricao: str):
        self.codigo = codigo
        self.descricao = descricao

    def __str__(self) -> str:
        return f"Produto[{self.codigo}] - {self.descricao}"

    def __eq__(self, outro) -> bool:
        if isinstance(outro, Produto):
            return self.codigo == outro.codigo
        return False

Encapsulamento

O encapsulamento é implementado através de membros privados. Para definir um atributo como privado, utiliza-se um prefixo de dois sublinhados no nome da variável (ex: __saldo). Da mesma forma, métodos privados seguem a mesma convenção de nomenclatura. Membros privados não podem ser acessados diretamente fora da classe, mas estão disponíveis para outros métodos internos da mesma classe.

Herança

A herança permite que uma classe filha reutilize atributos e métodos de uma classe pai, promovendo a reutilização de código. Na herança simples, uma classe deriva de uma única superclasse. Na herança múltipla, uma classe pode ter diversas classes pai, com resolução de conflitos de nomes seguindo a ordem de declaração (da esquerda para a direita).

Quando uma classe filha deseja alterar o comportamento herdado, ela pode sobrescrever (override) métodos ou atributos. Para acessar a implementação original da classe pai, utiliza-se a sintaxe super() ou referencia-se diretamente o nome da classe pai.


class Veiculo:
    def __init__(self, marca: str):
        self.marca = marca

    def exibir_info(self):
        print(f"Veículo da marca {self.marca}")

class Carro(Veiculo):
    def __init__(self, marca: str, modelo: str):
        super().__init__(marca)
        self.modelo = modelo

    def exibir_info(self):  # Sobrescrita do método
        print(f"Carro {self.marca} modelo {self.modelo}")

meu_carro = Carro("Toyota", "Corolla")
meu_carro.exibir_info()  # Saída: Carro Toyota modelo Corolla

Anotações de Tipo

As anotações de tipo em Python são indicadores opcionais que auxiliam no desenvolvimento, fornecendo dicas sobre os tipos de dados esperados para variáveis, parâmetros e valores de retorno. Ferramentas de IDE utilizam essas anotações para melhorar a autocompletação e a detecção de erros. É importante notar que as anotações não impõem verificações em tempo de execução; elas servem apenas como documentação e suporte estático.


def calcular_desconto(preco: float, porcentagem: float) -> float:
    return preco * (1 - porcentagem / 100)

# Uso de Union para tipos múltiplos
from typing import Union

def processar_entrada(dado: Union[int, str]) -> str:
    return str(dado)

Polimorfismo

O polimorfismo permite que diferentes classes implementem métodos com a mesma interface, resultando em comportamentos variados. Uma abordagem comum é definir uma classe abstrata com métodos sem implementação (métodos abstratos), que servem como contrato para as subclasses. Em Python, isso pode ser simulado utilizando a biblioteca abc.


from abc import ABC, abstractmethod

class Forma(ABC):
    @abstractmethod
    def area(self) -> float:
        pass

class Circulo(Forma):
    def __init__(self, raio: float):
        self.raio = raio

    def area(self) -> float:
        return 3.14159 * self.raio ** 2

class Retangulo(Forma):
    def __init__(self, largura: float, altura: float):
        self.largura = largura
        self.altura = altura

    def area(self) -> float:
        return self.largura * self.altura

def calcular_area_total(formas: list[Forma]) -> float:
    total = 0.0
    for forma in formas:
        total += forma.area()
    return total

Tags: Python Programação Orientada a Objetos classes Herança Polimorfismo

Publicado em 6-6 03:27 por Thomas