Aula 11: Sobrescrita de Métodos (Overriding)

Personalizando comportamentos em subclasses.

O Que Você Vai Aprender

Nesta aula, você aprenderá sobre a Sobrescrita de Métodos (Overriding), uma característica fundamental da herança em Programação Orientada a Objetos. Entenderá como uma subclasse pode fornecer sua própria implementação para um método já definido na superclasse, permitindo comportamentos específicos e flexibilidade na sua hierarquia de classes.

🔄 Conceito de Sobrescrita

Compreender como e por que uma subclasse pode redefinir um método da superclasse.

✨ Comportamento Específico

Ver como a sobrescrita permite que objetos de subclasses tenham comportamentos únicos para métodos herdados.

Conceito: Sobrescrita de Métodos (Overriding)

A Sobrescrita de Métodos, ou *Overriding*, acontece quando uma subclasse (classe filha) fornece uma implementação específica para um método que já está definido em sua superclasse (classe pai). Isso permite que objetos de diferentes classes se comportem de maneiras distintas, mesmo quando o mesmo nome de método é chamado.

Como Funciona

Quando você chama um método em um objeto, Python (e outras linguagens OO) primeiro procura esse método na classe do próprio objeto. Se o método não for encontrado lá, ele "sobe" na hierarquia de herança, procurando nas superclasses, até encontrar a primeira implementação. Com a sobrescrita, garantimos que a versão da subclasse seja utilizada.

class Animal:
    def fazer_som(self):
        print("Som genérico de animal")

class Gato(Animal):
    def fazer_som(self): # Sobrescrevendo o método fazer_som
        print("Miau!")

class Cachorro(Animal):
    def fazer_som(self): # Sobrescrevendo o método fazer_som
        print("Au Au!")

# Exemplo de uso:
# animal_generico = Animal()
# animal_generico.fazer_som() # Saída: Som genérico de animal

# meu_gato = Gato()
# meu_gato.fazer_som()      # Saída: Miau! (Método sobrescrito)

# meu_cachorro = Cachorro()
# meu_cachorro.fazer_som()  # Saída: Au Au! (Método sobrescrito)

Por que usar Sobrescrita?

  • **Comportamento Polimórfico:** Permite que objetos de diferentes classes respondam a uma mesma chamada de método de maneiras que são apropriadas para seu próprio tipo.
  • **Especialização:** Uma subclasse pode fornecer uma versão mais específica ou detalhada de um comportamento genérico definido na superclasse.
  • **Flexibilidade:** Facilita a manutenção e a extensão do código, pois novas subclasses podem ser criadas com comportamentos personalizados sem alterar o código existente.

Exemplo Prático: `Veiculo` e Suas Subclasses

Vamos ver a sobrescrita em ação com uma superclasse `Veiculo` e subclasses `Carro` e `Moto`, onde cada uma implementa seu próprio método `acelerar()`.

Classes `Veiculo`, `Carro` e `Moto`

class Veiculo:
    def __init__(self, marca, modelo):
        self.marca = marca
        self.modelo = modelo

    def acelerar(self):
        print(f"O {self.marca} {self.modelo} está acelerando de forma genérica.")

class Carro(Veiculo):
    def __init__(self, marca, modelo, portas):
        super().__init__(marca, modelo)
        self.portas = portas

    def acelerar(self): # Sobrescrevendo acelerar()
        print(f"O carro {self.marca} {self.modelo} de {self.portas} portas está acelerando suavemente.")

class Moto(Veiculo):
    def __init__(self, marca, modelo, cilindradas):
        super().__init__(marca, modelo)
        self.cilindradas = cilindradas

    def acelerar(self): # Sobrescrevendo acelerar()
        print(f"A moto {self.marca} {self.modelo} de {self.cilindradas}cc está acelerando com potência!")

# Exemplo de uso:
# meu_veiculo = Veiculo("Genérica", "Básico")
# meu_carro = Carro("Ford", "Fiesta", 4)
# minha_moto = Moto("Honda", "CBR500R", 500)

# meu_veiculo.acelerar()
# meu_carro.acelerar()
# minha_moto.acelerar()

Simulador: Comportamento de `Animal` e Suas Subclasses

Interaja com diferentes tipos de animais e observe como o método `fazer_som()` se comporta de forma diferente em cada um devido à sobrescrita.

Classes `Animal`, `Gato` e `Cachorro` (simuladas)

class Animal:
    def __init__(self, nome):
        self.nome = nome
    
    def fazer_som(self):
        return f"{self.nome} faz um som genérico de animal."

class Gato(Animal):
    def __init__(self, nome, cor):
        super().__init__(nome)
        self.cor = cor

    def fazer_som(self): # Sobrescrito
        return f"{self.nome} ({self.cor}) faz 'Miau!'."

class Cachorro(Animal):
    def __init__(self, nome, raca):
        super().__init__(nome)
        self.raca = raca

    def fazer_som(self): # Sobrescrito
        return f"{self.nome} da raça {self.raca} faz 'Au Au!'."

Teste os Animais

Desafios para Continuar

Coloque seus conhecimentos em prática com estes desafios de sobrescrita de métodos.

  • 1. Sobrescrevendo `apresentar()` em `Funcionario`

    Considere a classe `Pessoa` e `Funcionario` (onde `Funcionario` herda de `Pessoa`).

    Na classe `Funcionario`, sobrescreva o método `apresentar()` para que, além das informações da `Pessoa`, ele também exiba o `cargo` e o `salario` do funcionário.

    class Pessoa:
        def __init__(self, nome, idade):
            self.nome = nome
            self.idade = idade
        def apresentar(self):
            print(f"Olá, meu nome é {self.nome} e tenho {self.idade} anos.")
    
    class Funcionario(Pessoa):
        def __init__(self, nome, idade, cargo, salario):
            super().__init__(nome, idade)
            self.cargo = cargo
            self.salario = salario
        
        def apresentar(self): # Sobrescrita
            super().apresentar() # Chame o método da superclasse
            print(f"Eu sou {self.cargo} e meu salário é R${self.salario:.2f}.")
    
    # Exemplo:
    # func = Funcionario("Joana", 35, "Desenvolvedora", 4000.0)
    # func.apresentar()
    
  • 2. Calculando Bônus em `Gerente`

    Crie uma classe `Gerente` que herda de `Funcionario` (do exercício anterior).

    Na classe `Funcionario`, adicione um método `calcular_bonus()` que retorna `self.salario * 0.10` (10% do salário).

    Na classe `Gerente`, sobrescreva o método `calcular_bonus()` para que ele retorne `self.salario * 0.20` (20% do salário), refletindo um bônus maior para gerentes.

    # Adicione em Funcionario:
    # def calcular_bonus(self):
    #     return self.salario * 0.10
    
    # Crie a classe Gerente:
    # class Gerente(Funcionario):
    #     def __init__(self, nome, idade, cargo, salario, equipe_tamanho):
    #         super().__init__(nome, idade, cargo, salario)
    #         self.equipe_tamanho = equipe_tamanho
    #
    #     def calcular_bonus(self): # Sobrescrita
    #         return self.salario * 0.20
    
    # Exemplo:
    # gerente = Gerente("Pedro", 40, "Gerente", 7000.0, 10)
    # print(f"Bônus do Gerente: R${gerente.calcular_bonus():.2f}")