6.1 Herança — é fácil
Herança é um conceito fundamental de programação orientada a objetos (OO), que permite que uma classe (chamada de filha ou subclasse) herde campos e métodos de outra classe (chamada de pai ou superclasse).

Esse approach permite criar classes mais genéricas e reutilizar código, melhorando a organização e manutenção do código.
Por que usar herança?
Suponha que você precisa escrever algum código e decidiu fazer isso no formato de uma classe. Depois você descobre que no seu projeto já existe uma classe que faz quase tudo que você precisa na sua classe. Você poderia apenas copiar o código desta classe para a sua e aproveitar.
Ou você poderia "tipo copiar". Você pode declarar essa classe como sendo o pai da sua classe, e então Python vai adicionar ao seu código o comportamento da classe pai.
Imagine que você é a natureza e quer criar um Cachorro. O que seria mais rápido — criar um cachorro a partir de uma bactéria em bilhões de anos ou domesticar um lobo em 200 mil anos?
Exemplo de herança básica
Suponha que você tem uma classe pai Animal
com um campo name:
class Animal:
def __init__(self, name):
self.name = name
Queremos criar 2 classes-filhas para ele — Dog
e Cat
, e também adicionar a ambas o método speak
:
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
No exemplo acima, as classes-filhas Dog
e Cat
herdam de Animal
e acrescentam o método speak
.
Classe Dog
:
- Herdam o atributo
name
deAnimal
. - Acrescentam o método
speak
, que retorna uma string específica para cães.
Classe Cat
:
- Herdam o atributo
name
deAnimal
. - Acrescentam o método
speak
, que retorna uma string específica para gatos.
O código final fica assim:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # Vai mostrar: Buddy says Woof!
print(cat.speak()) # Vai mostrar: Whiskers says Meow!
Neste exemplo Animal
é a classe pai, e Dog
e Cat
são as classes-filhas. As classes-filhas herdam o atributo name
e o método __init__
da classe pai Animal
, mas adicionam métodos speak
.
6.2 Sob o capô da herança
Se você adicionou um pai a sua classe, isso é muito parecido com ter copiado o código da classe pai na sua classe.
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__(name) # Chamada do construtor da classe pai
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def __init__(self, name):
super().__init__(name) # Chamada do construtor da classe pai
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # Vai mostrar: Buddy says Woof!
print(cat.speak()) # Vai mostrar: Whiskers says Meow!
Isso não é exatamente preciso, mas se você nunca lidou com o conceito de herança, pode pensar assim por enquanto. Vamos adicionar mais detalhes depois.
6.3 Hierarquia de herança
Muitas vezes, ao projetar um modelo complexo de um grande grupo de classes, você pode se deparar com uma hierarquia inteira de herança.
Por exemplo, você tem uma classe Animal
— é a classe base para todos os animais:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement abstract method")
Até adicionamos a ela o método speak
, mas como um animal abstrato não fala, este método apenas lança uma exceção NotImplementedError
— é prática padrão.
Depois, adicionamos classes intermediárias que representam categorias de animais: Mammal
para mamíferos e Bird
para aves.
class Mammal(Animal):
def __init__(self, name, fur_color):
super().__init__(name) # Chamada do construtor da classe pai
self.fur_color = fur_color
class Bird(Animal):
def __init__(self, name, wing_span):
super().__init__(name) # Chamada do construtor da classe pai
self.wing_span = wing_span
def fly(self):
return f"{self.name} is flying with a wingspan of {self.wing_span} meters."
E finalmente, somente na etapa final aparecem as classes de espécies específicas de animais:
class Dog(Mammal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Mammal):
def speak(self):
return f"{self.name} says Meow!"
class Parrot(Bird):
def speak(self):
return f"{self.name} says Squawk!"
É com elas que o código final geralmente trabalha:
animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
for animal in animals:
print(animal.speak())
print(f"{dog.name} has {dog.fur_color} fur.") # Vai mostrar: Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.") # Vai mostrar: Whiskers has white fur.
print(parrot.fly()) # Vai mostrar: Polly is flying with a wingspan of 0.5 meters.
Embora tecnicamente não haja proibições para criar hierarquias com dezenas de ancestrais, é importante lembrar que sem necessidade é melhor manter a simplicidade. Na simplicidade está a força.
GO TO FULL VERSION