Herança Simples e Multinível
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 25 de 87.
Até agora, vimos classes estendendo uma classe pai diretamente. Mas a herança pode formar estruturas diferentes dependendo de como as classes se relacionam entre si. Vamos explorar os dois padrões principais: herança única e herança multinível.
Herança única é o que temos usado. Uma classe estende exatamente uma classe pai diretamente:
public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }Aqui, tanto Dog quanto Cat herdam de Animal, mas eles não herdam um do outro. Cada filho tem um pai direto.
Herança multinível cria uma cadeia onde uma classe estende outra classe, que por sua vez estende outra classe:
public class Animal {
public void eat() {
System.out.println("Eating");
}
}
public class Mammal extends Animal {
public void breathe() {
System.out.println("Breathing");
}
}
public class Dog extends Mammal {
public void bark() {
System.out.println("Barking");
}
}Nesta cadeia, Dog herda de Mammal, que herda de Animal. Um objeto Dog tem acesso a todos os métodos de toda a cadeia:
Dog dog = new Dog();
dog.eat(); // De Animal
dog.breathe(); // De Mammal
dog.bark(); // De DogLembre-se de que Object está no topo de cada cadeia. Portanto, nosso Dog na verdade tem quatro níveis: Object -> Animal -> Mammal -> Dog. O encadeamento de construtores flui por todos esses níveis ao criar um novo objeto.
Desafio
FácilVamos construir uma hierarquia de transporte que demonstre padrões de herança simples e multinível. Você criará uma cadeia de classes onde cada nível adiciona novas capacidades, mostrando como os métodos são herdados através de múltiplos níveis.
Você organizará seu código em quatro arquivos:
Vehicle.java: Crie a classe base no topo da sua hierarquia. Todo veículo deve ter:- Um campo privado para
brand(String) - Um construtor que aceita a marca
- Um método
getBrand()que retorna a marca - Um método
move()que imprime:[brand] is moving
- Um campo privado para
LandVehicle.java: Crie uma classe que estende Vehicle, representando o nível intermediário da sua cadeia multinível. Veículos terrestres adicionam comportamento específico para o solo:- Um campo privado para
wheels(int) - Um construtor que recebe brand e wheels, usando
super(brand)para a parte do pai - Um método
getWheels()que retorna a contagem de rodas - Um método
honk()que imprime:[brand] honks!
- Um campo privado para
Car.java: Crie uma classe que estende LandVehicle, completando sua cadeia de herança de três níveis. Carros adicionam seus próprios recursos especializados:- Um campo privado para
model(String) - Um construtor que recebe brand, wheels e model, usando
super(brand, wheels) - Um método
getModel()que retorna o modelo - Um método
displayInfo()que imprime:[brand] [model] with [wheels] wheels
- Um campo privado para
Main.java: Demonstre como um objeto Car tem acesso a métodos de todos os três níveis da hierarquia. Você receberá três entradas: brand (String), wheels (int) e model (String). Crie um Car e chame estes métodos em ordem:move()- herdado de Vehicle (avô)honk()- herdado de LandVehicle (pai)displayInfo()- definido no próprio Car
Você receberá três entradas: o nome da marca, o número de rodas e o nome do modelo.
Sua saída deve mostrar três linhas demonstrando como o objeto Car pode usar métodos de cada nível de sua cadeia de herança - desde o nível superior Vehicle até sua própria classe!
Folha de consulta
O Java suporta diferentes estruturas de herança. Os dois padrões principais são a herança simples e a herança multinível.
A herança simples ocorre quando uma classe estende exatamente uma classe pai diretamente:
public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }Tanto Dog quanto Cat herdam de Animal, mas não um do outro.
A herança multinível cria uma cadeia onde uma classe estende outra classe, que por sua vez estende outra classe:
public class Animal {
public void eat() {
System.out.println("Eating");
}
}
public class Mammal extends Animal {
public void breathe() {
System.out.println("Breathing");
}
}
public class Dog extends Mammal {
public void bark() {
System.out.println("Barking");
}
}Na herança multinível, uma classe filha tem acesso a todos os métodos de toda a cadeia de herança:
Dog dog = new Dog();
dog.eat(); // From Animal
dog.breathe(); // From Mammal
dog.bark(); // From DogToda hierarquia de classes tem Object no topo. O encadeamento de construtores flui por todos os níveis ao criar um novo objeto.
Experimente você mesmo
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler as entradas
String brand = scanner.nextLine();
int wheels = scanner.nextInt();
scanner.nextLine(); // consome a quebra de linha
String model = scanner.nextLine();
// TODO: Criar um objeto Car com os valores de entrada
// TODO: Chamar move() - herdado de Vehicle (avô)
// TODO: Chamar honk() - herdado de LandVehicle (pai)
// TODO: Chamar displayInfo() - definido no próprio Car
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator