Conceitos de POO para Python.

Daniel O. Malheiros
5 min readApr 13, 2021

--

Programação orientada a objetos (POO) é um dos paradigmas de programação mais usados. Neste texto, vamos entender alguns conceitos usados na POO utilizando a linguagem Python:

Herança:

Herança é a capacidade de uma classe de herdar propriedades e metodos de uma outra classe. A herança traz para nosso código organização, reusabilidade e hierarquia. Para utilizarmos, basta passar o nome da classe pai na declaração da(s) classe(s) filha(s), como no exemplo abaixo:

Perceba que “caracteristicas” não foi declarada dentro da classe cachorro ou gato, porem, por estes serem mamíferos, herdamos este método da classe pai. É importante notar que todas as classes que herdarem de cachorro automaticamente herdarão de mamífero (podemos chamá-las de classes “netas”), gerando a hierarquia que comentamos acima.

Em Python, ao contrário de varias outras linguagens, uma classe pode possuir heranças múltiplas, ou seja: uma classe filha com mais de uma classe pai! Basta separar por vírgulas ao declarar a classe filha. Por exemplo:

ornitorrinco tem dois R…..

Polimorfismo:

Polimorfismo é a capacidade que uma subclasse (classe filha) tem de ter métodos com o mesmo nome de sua superclasse (classe pai), e como o código é capaz de entender qual dos métodos deve ser chamado. Existem dois tipos de polimorfismos, a sobrescrita (method override) e a sobrecarga (method overload).

A sobrecarga consiste em, dentro da mesma classe, permitir mais de um método com o mesmo nome possuindo argumentos diferentes. A escolha de qual método irá ser chamado dependerá de acordo com seus argumentos. Podemos pensar em dois métodos com o mesmo nome Adição, onde em uma definição este receberá valores numéricos e irá soma-los e na segunda definição está receberá strings e irá concatená-los. Python, infelizmente não suporta a sobrecarga por default (há maneiras um pouco mais avançadas de fazê-lo, como com o uso do decorator @dispatch).

Sobrescrita é quando uma subclasse declara um método com o mesmo nome de um método herdado da superclasse. Aproveitando o exemplo anterior, criamos a classe CachorroRouco, que também possui o método latir.

Percebam que nosso cachorro rouco Bob passeia como um cachorro, come como um cachorro, mas late um pouco diferente. Isso acontece pois sobrescrevemos um de seus métodos herdados de Cachorro. Quando chamamos o método latir(), ele invocará o método da subclasse e não da superclasse! Podemos sobrescrever um método na sub e ainda chamarmos o resultado da super ao escrevermos dentro da declaração da função super().latir().

Classes abstratas:

Classes abstratas são aquelas que contém um ou mais métodos abstratos (métodos declarados, porém sem implementação — ou seja, somente a assinatura destes métodos sem corpo). Em Python, estas classes não podem ser instanciadas e precisam de subclasses que gerem implementação para os métodos, ou seja, as subclasses que herdam a classe abstrata devem sobrescrever obrigatoriamente seus métodos. São usadas apenas para serem herdadas, funcionando como uma superclasse e forçando hierarquia para todas as sub-classes.

Você pode se perguntar “Por que vou querer uma classe que não pode ser instanciada??”. O uso de classes abstratas criam um contrato que deverá ser respeitado por todos os programadores que usarem o código. O uso deste contrato ajudará a padronizar o código. Outro ponto é o DRY: (DRY — Don’t Repeat Yourself)! Em códigos longos, é comum termos diversas classes parecidas, e isso pode gerar uma confusão (tanto para quem fez, quanto para quem lê o código). Ao usarmos a classe abstrata como uma interface formal (falaremos mais abaixo), deixamos o código mais limpo e com menos chances de bugs.

Se a classe abstrata em Python funciona como uma interface formal…o que é uma interface informal? Qual a diferença?

A interface informal será bastante parecida com uma classe Python comum. Ela poderá definir métodos que posteriormente serão sobrescritos, mas não há obrigatoriedade para tal. Já uma interface formal funcionará como uma espécie de contrato, obrigando suas subclasses a implementar seus métodos.

TLDR: Uma classe abstrata cria uma interface comum para um conjunto de subclasses, reduzindo código duplicado e obrigando as subclasses a implementarem todos seus métodos abstratos. Exemplos:

Interface Informal:

Notem que a interface informal se parece exatamente como uma classe, e, ao criarmos a subclasse “BomDia”, não foi necessário sobrescrever todos seus métodos.

Interface formal:

Para utilizar classes abstratas, precisamos do import ABC (Abstract Base Classes). Vejam que ao tentar instanciar a classe abstrata, recebemos erro (e notem que o mesmo não acontece no exemplo acima).

Vamos continuar com um exemplo mais claro. Queremos montar uma banda! Para isso, faremos classes para cada músico e seu respectivo instrumento. Sabemos que uma banda é composta de pessoas (não me enviem vídeos de animais tocando instrumentos!). Podemos ter uma classe abstrata chamada Pessoa, que receberá os métodos abstratos comuns para todos os músicos, como Idade.

Perceba que ao instanciar julio como nosso guitarrista, recebemos um erro. Isso acontece pois não implementamos os métodos de nossa classe abstrata Pessoa em nossa classe Guitarrista. Esta é a obrigatoriedade que citamos acima!

Agora sim! Vamos testar com diversas subclasses:

Pronto, a banda está completa! Tire uns segundos para refletir quantos metodos em comum a classe abstrata Pessoa poderia ter (sexo, endereço, altura, etc). Podemos usar a classe abstrata para criar um contrato e deixar nosso código muito mais organizado!

Por hoje é só pessoal!

--

--

Daniel O. Malheiros
Daniel O. Malheiros

Written by Daniel O. Malheiros

Biomédico, programador Python e entusiasta de dados. Escrevo algumas crônicas as vezes.

No responses yet