Pilares da Programação Orientada a Objetos

Herança

A herança é um dos pilares fundamentais da Programação Orientada a Objetos (POO) que permite que uma classe (chamada subclasse ou classe derivada) herde atributos e métodos de outra classe (chamada superclasse ou classe base). Esta relação é frequentemente descrita como "é um tipo de" ou "é um".

Conceito Fundamental

A herança nos permite criar novas classes baseadas em classes existentes, permitindo o reaproveitamento de código e estabelecendo uma hierarquia entre classes. A classe filha (subclasse) herda características da classe pai (superclasse), podendo adicionar novos atributos e métodos, ou mesmo sobrescrever os existentes.

Exemplo: Um Cachorro é um Animal, então a classe Cachorro pode herdar da classe Animal.

Tipos de Herança

1. Herança Simples

Na herança simples, uma subclasse herda características de uma única superclasse. É o tipo de herança mais comum e suportado por todas as linguagens orientadas a objetos.

                
class Animal {
    protected String nome;
    
    public void comer() {
        System.out.println(nome + " está comendo.");
    }
}

class Cachorro extends Animal {
    public void latir() {
        System.out.println(nome + " está latindo.");
    }
}
                
            

2. Herança Múltipla

Na herança múltipla, uma subclasse pode herdar características de mais de uma superclasse. Nem todas as linguagens suportam herança múltipla diretamente (como Java), mas algumas oferecem alternativas como interfaces.

                
// Exemplo em C++
class DispositivoEletronico {
public:
    void ligar() { cout << "Dispositivo ligado"; }
};

class DispositivoPortatil {
public:
    void carregar() { cout << "Dispositivo carregando"; }
};

class Smartphone : public DispositivoEletronico, public DispositivoPortatil {
public:
    void fazerChamada() { cout << "Fazendo chamada"; }
};
                
            

3. Herança Multinível

Na herança multinível, temos uma cadeia de herança. Por exemplo, a classe C herda da classe B, que por sua vez herda da classe A.

                
class Animal {
    protected String nome;
    
    public void comer() {
        System.out.println(nome + " está comendo.");
    }
}

class Mamifero extends Animal {
    public void amamentar() {
        System.out.println(nome + " está amamentando.");
    }
}

class Cachorro extends Mamifero {
    public void latir() {
        System.out.println(nome + " está latindo.");
    }
}
                
            

4. Herança Hierárquica

Na herança hierárquica, várias subclasses herdam de uma única superclasse.

                
class Animal {
    protected String nome;
    
    public void comer() {
        System.out.println(nome + " está comendo.");
    }
}

class Cachorro extends Animal {
    public void latir() {
        System.out.println(nome + " está latindo.");
    }
}

class Gato extends Animal {
    public void miar() {
        System.out.println(nome + " está miando.");
    }
}
                
            

Benefícios da Herança

Desafios e Considerações

Herança vs. Composição

Existe um princípio importante na POO: "Prefira composição sobre herança". Isto porque a herança estabelece uma relação rígida entre classes, enquanto a composição permite maior flexibilidade e menor acoplamento.

                
// Composição
class Motor {
    public void ligar() { ... }
}

class Carro {
    private Motor motor; // Carro TEM UM motor
    
    public Carro() {
        this.motor = new Motor();
    }
    
    public void ligar() {
        motor.ligar();
    }
}
                
            

Implementação em Diferentes Linguagens

Java

                
// Java usa a palavra-chave 'extends'
public class Animal {
    protected String nome;
    
    public void comer() {
        System.out.println(nome + " está comendo.");
    }
}

public class Cachorro extends Animal {
    public void latir() {
        System.out.println(nome + " está latindo.");
    }
}
                
            

Python

                
# Python coloca a superclasse entre parênteses
class Animal:
    def __init__(self, nome):
        self.nome = nome
    
    def comer(self):
        print(f"{self.nome} está comendo.")

class Cachorro(Animal):
    def latir(self):
        print(f"{self.nome} está latindo.")
                
            

C#

                
// C# usa : para indicar herança
public class Animal
{
    protected string Nome;
    
    public void Comer()
    {
        Console.WriteLine($"{Nome} está comendo.");
    }
}

public class Cachorro : Animal
{
    public void Latir()
    {
        Console.WriteLine($"{Nome} está latindo.");
    }
}
                
            

Conclusão

A herança é uma ferramenta poderosa na programação orientada a objetos, permitindo modelar relações do mundo real de forma natural e reutilizar código de maneira eficiente. No entanto, deve ser usada com sabedoria, considerando sempre se a relação é verdadeiramente "é-um" e se não seria melhor utilizar a composição em determinados casos.