Herança

Herança é uma das características centrais da OOP, permitindo reutilização de código.

O que é Herança

Herança permite que uma subclasse herde atributos e métodos de uma classe pai, permitindo reutilização de código.

Benefícios da Herança

Benefício Descrição
Reutilização de código Não é necessário reescrever o código da classe pai
Extensibilidade Subclasses podem adicionar seus próprios atributos e métodos
Base para polimorfismo Herança é um pré-requisito para polimorfismo

A Palavra-chave extends

Sintaxe

JAVA
public class ClasseFilha extends ClassePai {
    // Atributos e métodos específicos da classe filha
}

Exemplo: Herança

JAVA
// Classe pai
public class Animal {
    String name;
    int age;
    
    public void eat() {
        System.out.println(name + " está comendo");
    }
    
    public void sleep() {
        System.out.println(name + " está dormindo");
    }
}

// Classe filha
public class Dog extends Animal {
    String breed;
    
    public void bark() {
        System.out.println(name + " está latindo");
    }
}

public class Cat extends Animal {
    String color;
    
    public void meow() {
        System.out.println(name + " está miando");
    }
}

public class InheritanceDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "Buddy";
        dog.age = 3;
        dog.breed = "Golden Retriever";
        
        dog.eat();    // Buddy está comendo (herdado de Animal)
        dog.sleep();  // Buddy está dormindo (herdado de Animal)
        dog.bark();   // Buddy está latindo (método próprio do Dog)
        
        Cat cat = new Cat();
        cat.name = "Whiskers";
        cat.age = 2;
        cat.color = "White";
        
        cat.eat();    // Whiskers está comendo
        cat.meow();   // Whiskers está miando
    }
}
▶ Experimente

A Palavra-chave super

super é uma referência à classe pai.

Uso 1: Chamar Construtor Pai

JAVA
public class Animal {
    String name;
    int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Dog extends Animal {
    String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // Chamar construtor pai
        this.breed = breed;
    }
}

Uso 2: Chamar Método Pai

JAVA
public class Animal {
    public void eat() {
        System.out.println("Animal está comendo");
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        super.eat();  // Chamar eat do pai
        System.out.println("Cão está roendo um osso");
    }
}

Exemplo: Usando super

JAVA
public class Person {
    protected String name;
    protected int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void showInfo() {
        System.out.println("Nome: " + name + ", Idade: " + age);
    }
}

public class Student extends Person {
    private double score;
    
    public Student(String name, int age, double score) {
        super(name, age);  // Chamar construtor pai
        this.score = score;
    }
    
    @Override
    public void showInfo() {
        super.showInfo();  // Chamar showInfo do pai
        System.out.println("Pontuação: " + score);
    }
}

public class SuperDemo {
    public static void main(String[] args) {
        Student stu = new Student("Alice", 20, 95.5);
        stu.showInfo();
        // Nome: Alice, Idade: 20
        // Pontuação: 95.5
    }
}
▶ Experimente

Sobrescrita de Métodos

Subclasses podem sobrescrever métodos da classe pai para implementar comportamento diferente.

Regras de Sobrescrita

Regra Descrição
Mesmo nome de método Obrigatório
Mesma lista de parâmetros Obrigatório
Mesmo tipo de retorno Ou uma subclasse do tipo de retorno do pai
Acesso não pode ser mais restritivo Pode ser mais permissivo

Anotação @Override

JAVA
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Cão está roendo um osso");
    }
}
💡 Recomendação: Sempre adicione a anotação @Override ao sobrescrever métodos. O compilador verificará se a sobrescrita está correta.

A Classe Object

Todas as classes herdam direta ou indiretamente da classe Object.

Métodos Comuns de Object

Método Descrição
toString() Retorna uma representação em string do objeto
equals() Compara objetos para igualdade
hashCode() Retorna o código hash do objeto
getClass() Retorna informações da classe do objeto

Sobrescrevendo toString()

JAVA
public class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
    
    public static void main(String[] args) {
        Student stu = new Student("Alice", 20);
        System.out.println(stu);  // Chama toString() automaticamente
        // Saída: Student{name='Alice', age=20}
    }
}

Sobrescrevendo equals()

JAVA
public class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student other = (Student) obj;
        return age == other.age && name.equals(other.name);
    }
    
    @Override
    public int hashCode() {
        return name.hashCode() * 31 + age;
    }
    
    public static void main(String[] args) {
        Student s1 = new Student("Alice", 20);
        Student s2 = new Student("Alice", 20);
        
        System.out.println(s1 == s2);      // false (objetos diferentes)
        System.out.println(s1.equals(s2)); // true (mesmo conteúdo)
    }
}

instanceof

O operador instanceof verifica se um objeto é uma instância de uma classe específica.

JAVA
public class InstanceofDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        
        System.out.println(dog instanceof Dog);    // true
        System.out.println(dog instanceof Animal); // true
        System.out.println(dog instanceof Object); // true
    }
}

Notas sobre Herança

Nota Descrição
Herança simples Java só suporta herança simples
Não pode herdar private Membros privados não podem ser herdados
Não pode herdar construtores Construtores não podem ser herdados
Object é classe raiz Todas as classes herdam de Object

❓ Perguntas Frequentes

P: Por que Java não suporta herança múltipla? R: Para evitar o problema do diamante (ambiguidade quando múltiplos pais têm o mesmo método). Java usa interfaces para funcionalidade similar.

P: Quando devo usar herança? R: Quando duas classes têm uma relação "é-um", como Cão é um Animal.

P: Como escolher entre herança e composição? R: Prefira composição (relação "tem-um"). Herança aumenta o acoplamento.

📖 Resumo

📝 Exercícios

  1. Hierarquia de formas: Defina uma classe pai Shape com subclasses Circle e Rectangle, calcule áreas
  2. Hierarquia de funcionários: Defina uma classe pai Employee com subclasses Manager e Developer
  3. toString/equals: Sobrescreva os métodos toString e equals em uma classe Student

Próxima Lição

Na próxima lição, aprenderemos sobre Polimorfismo e Abstração — características centrais da OOP.

100%