Atualizado: 04/11/2024

Herança - Python

A herança permite criar uma nova classe com base em uma já existente. Juntamente com a encapsulação, a herança é um dos pilares da programação orientada a objetos.

Os principais conceitos na herança são subclasse e superclasse. A subclasse herda todos os atributos e métodos públicos da superclasse. A superclasse também é chamada de classe base ou classe pai, enquanto a subclasse é conhecida como classe derivada ou classe filha.

O seguinte é o exemplo da sintaxe para herança de classes:

class Subclasse(Superclasse):
    métodos_subclasse

Por exemplo, temos uma classe Person, que representa uma pessoa:

class Person:
 
    def __init__(self, name):
        self.__name = name  # nome da pessoa
 
    @property
    def name(self):
        return self.__name
     
    def display_info(self):
        print(f"Name: {self.__name}")

Agora, vamos supor que precisamos de uma classe Employee para representar um funcionário de uma empresa. Podemos criar essa classe do zero:

class Employee:
 
    def __init__(self, name):
        self.__name = name  # nome do funcionário
 
    @property
    def name(self):
        return self.__name
 
    def display_info(self):
        print(f"Name: {self.__name}")
 
    def work(self):
        print(f"{self.name} works")

No entanto, a classe Employee possui os mesmos atributos e métodos que a classe Person, pois um funcionário é, afinal, uma pessoa. O código da classe Employee repete a funcionalidade da classe Person, exceto pelo método work. Para evitar essa duplicação de código, podemos aplicar a herança.

Assim, vamos herdar a classe Employee da classe Person:

class Person:
 
    def __init__(self, name):
        self.__name = name  # nome da pessoa
 
    @property
    def name(self):
        return self.__name
 
    def display_info(self):
        print(f"Name: {self.__name}")
 
 
class Employee(Person):
 
    def work(self):
        print(f"{self.name} works")
 
tom = Employee("Tom")
print(tom.name)     # Tom
tom.display_info()  # Name: Tom
tom.work()          # Tom works

A classe Employee herda totalmente a funcionalidade da classe Person e adiciona seu próprio método work. Dessa forma, ao criar um objeto da classe Employee, podemos utilizar o construtor herdado de Person:

tom = Employee("Tom")

Também podemos acessar os atributos e métodos herdados:

print(tom.name)     # Tom
tom.display_info()  # Name: Tom

Vale lembrar que Employee não pode acessar atributos privados da superclasse, como o atributo __name. Por exemplo, não é possível usar self.__name diretamente no método work:

def work(self):
    print(f"{self.__name} works")   # Erro!

Herança Múltipla

Uma característica distintiva do Python é o suporte à herança múltipla, onde uma classe pode herdar de várias classes:

# Classe Employee
class Employee:
    def work(self):
        print("Employee works")
    
# Classe Student
class Student:
    def study(self):
        print("Student studies")
    
class WorkingStudent(Employee, Student):   # Herança de Employee e Student
    pass

tom = WorkingStudent()
tom.work()   # Employee works
tom.study()  # Student studies

Neste exemplo, WorkingStudent representa um estudante que trabalha, herdando as funcionalidades de Employee e Student. Assim, podemos chamar métodos de ambas as classes:

tom = WorkingStudent()
tom.work()   # Employee works
tom.study()  # Student studies

Os métodos herdados podem ter funcionalidade mais complexa, como mostrado a seguir:

class Employee:
 
    def __init__(self, name):
        self.__name = name
 
    @property
    def name(self):
        return self.__name
 
    def work(self):
        print(f"{self.name} works")
 
 
class Student:
 
    def __init__(self, name):
        self.__name = name
 
    @property
    def name(self):
        return self.__name
 
    def study(self):
        print(f"{self.name} studies")
 
 
class WorkingStudent(Employee, Student):
    pass
 
tom = WorkingStudent("Tom")
tom.work()    # Tom works
tom.study()   # Tom studies

Embora a herança múltipla seja prática, ela pode gerar confusão caso ambas as classes possuam métodos ou atributos com os mesmos nomes. Veja o exemplo:

class Employee:
    def do(self):
        print("Employee works")
  
class Student:
    def do(self):
        print("Student studies")
  
class WorkingStudent(Employee, Student):
    pass
 
tom = WorkingStudent()
tom.do()     # Qual método será usado?

No exemplo, ambas as classes Employee e Student possuem um método do, cada um com um propósito distinto. Quando definimos WorkingStudent com Employee primeiro, o método do de Employee é o que será chamado.

Para alterar a preferência, basta trocar a ordem das classes:

class WorkingStudent(Student, Employee)

É possível verificar a ordem de aplicação da funcionalidade das classes bases com o atributo __mro__ ou o método mro():

print(WorkingStudent.__mro__)  
print(WorkingStudent.mro())   

Estes métodos retorna uma listam de classes na ordem em que os métodos são procurados pelo Python.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com