A herança é um dos pilares fundamentais da Programação Orientada a Objetos (POO). Esse conceito permite que uma classe herde atributos e comportamentos de outra classe, estabelecendo uma relação hierárquica entre elas. A classe que fornece essas características é chamada de classe base, classe pai ou superclasse, enquanto a classe que herda é conhecida como classe derivada, classe filha ou subclasse.
Na prática, a herança representa uma relação do tipo “é um”. Isso significa que a classe filha é uma especialização da classe pai. Por exemplo, se existe uma classe chamada Veiculo, uma classe Carro pode herdar dela, pois um carro é um tipo específico de veículo. Essa abordagem facilita a reutilização de código e ajuda a manter uma estrutura mais organizada e coerente dentro do sistema.
Por que usar herança em POO ?
O uso da herança está diretamente relacionado à necessidade de reutilizar código e de representar relações naturais entre entidades do domínio do problema. Em sistemas maiores, é comum que diferentes classes compartilhem comportamentos e características semelhantes. A herança evita que esses elementos sejam reescritos repetidamente, centralizando-os em uma classe base.
Além disso, a herança contribui para a extensibilidade do software. Quando novas funcionalidades precisam ser adicionadas, muitas vezes é possível criar novas subclasses que estendem o comportamento existente, sem a necessidade de modificar o código já testado e em funcionamento. Isso reduz riscos e torna a manutenção mais segura.
Vantagens
Uma das principais vantagens da herança é a reutilização de código. Métodos e atributos definidos em uma superclasse podem ser utilizados por diversas subclasses, diminuindo a duplicação e tornando o código mais limpo e consistente.
Outra vantagem importante é a organização do sistema. A herança permite estruturar o código de forma hierárquica, facilitando o entendimento das relações entre as classes. Isso torna o sistema mais legível, especialmente quando o domínio do problema é bem modelado.
A herança também favorece o polimorfismo, permitindo que objetos de classes diferentes sejam tratados de forma uniforme. Isso possibilita a escrita de códigos mais genéricos e flexíveis, que trabalham com abstrações em vez de implementações concretas.
Desvantagens
Apesar de seus benefícios, a herança deve ser utilizada com cautela. Um dos principais problemas é o acoplamento forte entre classes. Quando uma classe filha depende diretamente da implementação da classe pai, alterações na superclasse podem impactar todas as subclasses, tornando o sistema mais frágil.
Outro ponto negativo é o uso inadequado da herança para relações que não representam corretamente o conceito “é um”. Quando a herança é aplicada apenas para reaproveitar código, sem uma relação semântica adequada, o design do sistema pode se tornar confuso e difícil de manter.
Além disso, hierarquias muito profundas podem complicar a compreensão do código. Quanto mais níveis de herança existem, mais difícil se torna rastrear a origem de um comportamento específico, o que pode aumentar a complexidade da manutenção.
Exemplo prático da aplicação do conceito de herança

Considere um sistema simples para gerenciamento de funcionários. Todos os funcionários compartilham características básicas, como nome e salário, mas cada tipo de funcionário possui regras diferentes para o cálculo de bônus. Primeiro, temos a classe base Funcionario:
public class Funcionario {
protected String nome;
protected double salario;
public Funcionario(String nome, double salario) {
this.nome = nome;
this.salario = salario;
}
public double calcularBonus() {
return salario * 0.10;
}
public void exibirDados() {
System.out.println("Nome: " + nome);
System.out.println("Salário: " + salario);
System.out.println("Bônus: " + calcularBonus());
}
}
Essa classe define os atributos e comportamentos comuns a todos os funcionários. Em seguida, criamos uma classe que herda de Funcionario, representando um gerente:
public class Gerente extends Funcionario {
public Gerente(String nome, double salario) {
super(nome, salario);
}
@Override
public double calcularBonus() {
return salario * 0.20;
}
}
Nesse caso, a classe Gerente herda os atributos e métodos da classe Funcionario, mas redefine o método calcularBonus, pois o gerente possui uma regra diferente para o cálculo do bônus. Por fim, podemos utilizar essas classes da seguinte forma:
public class Main {
public static void main(String[] args) {
Funcionario funcionario = new Funcionario("Carlos", 3000);
Funcionario gerente = new Gerente("Ana", 6000);
funcionario.exibirDados();
System.out.println("-----");
gerente.exibirDados();
}
}
Mesmo tratando ambos como Funcionario, o comportamento do método calcularBonus varia conforme o tipo real do objeto. Esse é um exemplo claro de herança combinada com polimorfismo, mostrando como o conceito contribui para a flexibilidade e extensibilidade do sistema.

Muito bom!!