Pessoal, estou com algumas dúvidas relacionadas a orientação a objetos no Python, o que é classe abstrata e interface? Quais são suas diferenças? E como posso introduzir a ideia em meu código?
Pessoal, estou com algumas dúvidas relacionadas a orientação a objetos no Python, o que é classe abstrata e interface? Quais são suas diferenças? E como posso introduzir a ideia em meu código?
Classe Abstrata: Classe que não pode ser utilizada para instanciar objetos diretamente (É o oposto de "Classe Concreta").
Interface: Conjunto de métodos a serem utilizados pelo usuário.
Classes Abstratas são utilizadas como base para criar subclasses concretas. Essas subclasses herdam e implementam (ou "concretizam") os métodos da classe mãe.
A Classe Abstrata é a "ferramenta" da linguagem Python que te ajuda a definir uma interface padrão (conceito), que só será implementada mesmo nas subclasses. Isso é muito usado no Design Pattern Strategy.
Imagine que você é desenvolvedor de um site onde o usuário pode fazer upload de planilhas para serem analisadas.
Inicialmente, eram aceitas planilhas apenas em formato .xlsx
, mas depois pediram para o site aceitar .csv
também. E conforme o tempo vai passando os clientes vão sempre pedindo mais e mais extensões diferentes (.xml
, .json
, etc)
O seu código correria o risco de virar uma bagunça! Cheio de if
e elses
para cada extensão nova.
A solução é criar uma interface padrão, implementada usando uma Classe Abstrata:
class SpreadsheetStrategy (ABC): # Classe Abstrata
@abstractmethod
def read(self, file): -> pd.DataFrame # Método Abstrato
pass # Implementado apenas nas subclasses concretas
@abstractmethod
def parse(self): # Método Abstrato
pass
Interface:
No exemplo, os métodos read
e parse
são a interface, que será implementada nas subclasses.
Classe Abstrata:
No exemplo, a classe SpreadSheet é Abstrata porque ela herda de ABC. Note que seus métodos são decorados com @abstractmethod
class XlsxStrategy (SpreadsheetStrategy): # Classe Concreta
def read(self, file): -> pd.DataFrame # Método Concreto
# Código para ler .xlsx
def parse(self): # Método Concreto
# Código para analizar .xlsx
class CsvStrategy (SpreadsheetStrategy): # Classe Concreta
def read(self, file): -> pd.DataFrame # Método Concreto
# Código para ler .csv
def parse(self): # Método Concreto
# Código para analizar .csv
Toda vez que você precisar dar suporte a uma nova extensão de arquivo, é só criar mais uma classe com a estratégia para lidar com ela, sempre seguindo a mesma interface.
O código cliente não precisa saber os detalhes internos da implementação, ele só vai chamar os métodos da interface (read
e parse
) sem se preocupar.
Imagine um botão no seu site ou um objeto qualquer podendo chamar diretamente:
self.strategy.parse()
Ótima explicação, ajudou bastante