Programação Orientada a Objetos em Python: Conceitos e Prática

Na programação orientada a objetos, uma classe funciona como um molde que define a estrutura e o comportamanto que seus objetos terão. O objeto, por sua vez, é a materialização concreta dessa classe. Cada objeto possui características próprias (atributos) e ações que pode executar (métodos). Ao agruparmos objetos que compartilham propriedades e comportamentos similares, abstraímos esses elementos comuns para formar uma classe.

Criando Classes em Python

A palavra-chave class é utilizada para declarar uma classe. Dentro dela, definimos funções que representam os métodos do objeto. Veja um exemplo:

class Aluno:

    def __init__(self, nome, idade):
        self.nome = nome
        self.idade = idade

    def estudar(self, disciplina):
        print(f'{self.nome} está estudando {disciplina}.')

    def assistir_filme(self):
        if self.idade < 18:
            print(f'{self.nome} só pode assistir filmes infantis.')
        else:
            print(f'{self.nome} está assistindo um filme para adultos.')

Instanciando e Utilizando Objetos

Após definir a classe, podemos criar instâncias e interagir com elas:

def executar():
    aluno1 = Aluno('Carlos', 20)
    aluno1.estudar('Estrutura de Dados')
    aluno1.assistir_filme()

    aluno2 = Aluno('Ana', 15)
    aluno2.estudar('Matemática')
    aluno2.assistir_filme()

if __name__ == '__main__':
    executar()

Controle de Visibilidade de Atributos e Métodos

Em linguagens como Java e C#, existe controle rígido sobre a visibildiade de atributos e métodos (private, protected, public). Em Python, existem essencialmente dois níveis: público e privado. Para marcar um atributo ou método como privado, basta prefixá-lo com dois sublinhados (__).

class Exemplo:

    def __init__(self, valor):
        self.__valor = valor

    def __exibir(self):
        print(self.__valor)

def executar():
    obj = Exemplo('dados secretos')
    # obj.__exibir()  # gera AttributeError
    # print(obj.__valor)  # gera AttributeError

No entanto, Python não impede rigorosamente o acesso a membros privados. Na verdade, o interpretador renomeia esses membros aplicando uma técnica chamada name mangling, adicionando o nome da classe como prefixo. Assim, ainda é possível acessá-los:

def executar():
    obj = Exemplo('dados secretos')
    obj._Exemplo__exibir()
    print(obj._Exemplo__valor)

Essa flexibilidade reflete a filosofia do Python, onde se assume que desenvolvedores são responsáveis por suas próprias decisões. Na prática, a convenção amplamente adotada é utilizar um único sublinhado (_) como prefixo para indicar que um atributo ou método deve ser tratado como protegido, sinalizando que o acesso externo deve ser evitado, embora não seja proibido pela linguagem.

Pilares da Orientação a Objetos

Os três pilares fundamentais são: encapsulamento, herança e polimorfismo. O encapsulamento consiste em ocultar os detalhes internos de implementação, expondo apenas uma interface simples para interação. Quando definimos métodos em uma classe, estamos encapsulando dados e suas operações. O usuário do objeto precisa apenas conhecer a assinatura dos métodos (parâmetros e retorno), sem se preocupar com a lógica interna.

Exercícios Práticos

Exercício 1: Relógio Digital

from time import sleep

class Cronometro:
    """Representa um relógio digital simples."""

    def __init__(self, hora=0, minuto=0, segundo=0):
        self._hora = hora
        self._minuto = minuto
        self._segundo = segundo

    def avancar(self):
        """Incrementa o tempo em um segundo."""
        self._segundo += 1
        if self._segundo >= 60:
            self._segundo = 0
            self._minuto += 1
            if self._minuto >= 60:
                self._minuto = 0
                self._hora += 1
                if self._hora >= 24:
                    self._hora = 0

    def hora_formatada(self):
        """Retorna o horário no formato HH:MM:SS."""
        return f'{self._hora:02d}:{self._minuto:02d}:{self._segundo:02d}'

def executar():
    relogio = Cronometro(23, 59, 58)
    while True:
        print(relogio.hora_formatada())
        sleep(1)
        relogio.avancar()

if __name__ == '__main__':
    executar()

Exercício 2: Ponto no Plano Cartesiano

from math import sqrt

class Coordenada:
    """Representa um ponto em um plano 2D."""

    def __init__(self, eixo_x=0, eixo_y=0):
        self.x = eixo_x
        self.y = eixo_y

    def deslocar_para(self, novo_x, novo_y):
        """Define uma nova posição absoluta."""
        self.x = novo_x
        self.y = novo_y

    def deslocar_por(self, delta_x, delta_y):
        """Move o ponto por um deslocamento relativo."""
        self.x += delta_x
        self.y += delta_y

    def distancia_ate(self, outro_ponto):
        """Calcula a distância euclidiana até outro ponto."""
        diff_x = self.x - outro_ponto.x
        diff_y = self.y - outro_ponto.y
        return sqrt(diff_x ** 2 + diff_y ** 2)

    def __str__(self):
        return f'({self.x}, {self.y})'

def executar():
    ponto_a = Coordenada(3, 5)
    ponto_b = Coordenada()
    print(ponto_a)
    print(ponto_b)
    ponto_b.deslocar_por(-1, 2)
    print(ponto_b)
    print(ponto_a.distancia_ate(ponto_b))

if __name__ == '__main__':
    executar()

Tags: Python OOP classes objetos encapsulamento

Publicado em 6-27 22:16