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
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
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
Employee
Person
work
Assim, vamos herdar a classe Employee
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
Person
work
Employee
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
__name
self.__name
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
Employee
Student
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
Student
do
WorkingStudent
Employee
do
Employee
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__
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.