Java oferece suporte à reutilização de classes por meio de herança e composição. Este tutorial de duas partes ensina como usar herança em seus programas Java.
O que você aprenderá neste tutorial Java
A primeira metade desta introdução à herança Java ensina como usar o extends
palavra-chave para derivar uma classe filha de uma classe pai, invocar construtores e métodos da classe pai e substituir métodos:
- O que é herança em Java?
- Herança única e herança múltipla
- Como usar a palavra-chave extends em Java
- Compreendendo a hierarquia de classes Java
- Quando usar substituição de método versus sobrecarga de método
Baixe o código-fonte de aplicativos de exemplo neste tutorial. Criado por Jeff Friesen.
O que é herança em Java?
Herança é uma construção de programação que os desenvolvedores de software usam para estabelecer é um relacionamento entre categorias. A herança nos permite derivar categorias mais específicas de outras mais genéricas. A categoria mais específica é um tipo de categoria mais genérica. Por exemplo, uma conta corrente é um tipo de conta na qual você pode fazer depósitos e saques. Da mesma forma, um caminhão é um tipo de veículo usado para transportar itens grandes.
A herança pode passar por vários níveis, levando a categorias cada vez mais específicas. Como exemplo, a Figura 1 mostra carro e caminhão herdados de veículo; perua herdada de carro; e caminhão de lixo herdado de caminhão. As setas apontam de categorias “filhos” mais específicas (em baixo) para categorias “pais” menos específicas (em cima).
Figura 1. Um par de hierarquias de herança está enraizado na categoria de veículo comum
Herança única e herança múltipla
O exemplo na Figura 1 ilustra herança única em que uma categoria filha herda estados e comportamentos de uma categoria pai imediata. Em contraste, herança múltipla permite que uma categoria filha herde estados e comportamentos de duas ou mais categorias pai imediatas. A hierarquia na Figura 2 ilustra a herança múltipla.

Figura 2. Hovercraft multiplica heranças das categorias de veículos terrestres e aquáticos
As categorias são descritas por classes. Java suporta herança única por meio de extensão de classe, em que uma classe herda diretamente campos e métodos acessíveis de outra classe, estendendo essa classe. Entretanto, Java não suporta herança múltipla por meio de extensão de classe.
Ao visualizar uma hierarquia de herança, você pode detectar facilmente herança múltipla pela presença de um padrão de losango. A Figura 2 mostra esse padrão no contexto de veículo, veículo terrestre, veículo aquático e hovercraft.
Como usar a palavra-chave extends em Java
Java suporta extensão de classe através do extends
palavra-chave. Quando presente, extends
especifica um relacionamento pai-filho entre duas classes. Abaixo eu uso extends
estabelecer uma relação entre as classes Vehicle
e Car
e depois entre Account
e SavingsAccount
:
Listagem 1. A palavra-chave 'extends' especifica um relacionamento pai-filho
class Vehicle
{
// member declarations
}
class Car extends Vehicle
{
// inherit accessible members from Vehicle
// provide own member declarations
}
class Account
{
// member declarations
}
class SavingsAccount extends Account
{
// inherit accessible members from Account
// provide own member declarations
}
O extends
palavra-chave é especificada após o nome da classe e antes de outro nome de classe. O nome da classe antes extends
identifica o filho e o nome da classe após extends
identifica o pai. É impossível especificar vários nomes de classes depois extends
porque Java não suporta herança múltipla baseada em classe.
Estes exemplos codificam relacionamentos é-a: Car
é um especializado Vehicle
e SavingsAccount
é um especializado Account
. Vehicle
e Account
são conhecidos como classes básicas, classes parentaisou superclasses. Car
e SavingsAccount
são conhecidos como classes derivadas, aulas infantisou subclasses.
As classes filhas herdam campos e métodos acessíveis de suas classes pai e de outros ancestrais. Eles nunca herdam construtores, entretanto. Em vez disso, as classes filhas declaram seus próprios construtores. Além disso, eles podem declarar seus próprios campos e métodos para diferenciá-los de seus pais. Considere a Listagem 2.
Listagem 2. Uma classe pai Account
class Account
{
private String name;
private long amount;
Account(String name, long amount)
{
this.name = name;
setAmount(amount);
}
void deposit(long amount)
{
this.amount += amount;
}
String getName()
{
return name;
}
long getAmount()
{
return amount;
}
void setAmount(long amount)
{
this.amount = amount;
}
}
A Listagem 2 descreve uma classe genérica de conta bancária que possui um nome e um valor inicial, ambos definidos no construtor. Além disso, permite que os usuários façam depósitos. (Você pode fazer saques depositando quantias negativas de dinheiro, mas ignoraremos essa possibilidade.) Observe que o nome da conta deve ser definido quando uma conta é criada.
A Listagem 3 apresenta um SavingsAccount
classe filha que estende seu Account
classe pai.
Listagem 3. Uma classe filha SavingsAccount estende sua classe pai Account
class SavingsAccount extends Account
{
SavingsAccount(long amount)
{
super("savings", amount);
}
}
O SavingsAccount
class é trivial porque não precisa declarar campos ou métodos adicionais. No entanto, ele declara um construtor que inicializa os campos em seu Account
superclasse. A inicialização acontece quando Account
O construtor de é chamado via Java super
palavra-chave, seguida por uma lista de argumentos entre parênteses.
A Listagem 4 estende ainda mais Account
com um CheckingAccount
aula.
Listagem 4. Uma classe filha CheckingAccount estende sua classe pai Account
class CheckingAccount extends Account
{
CheckingAccount(long amount)
{
super("checking", amount);
}
void withdraw(long amount)
{
setAmount(getAmount() - amount);
}
}
CheckingAccount
é um pouco mais substancial do que SavingsAccount
porque declara um withdraw()
método. Observe as chamadas deste método para setAmount()
e getAmount()
qual CheckingAccount
herda de Account
. Você não pode acessar diretamente o amount
campo em Account
porque este campo é declarado private
(veja Listagem 2).
Compreendendo a hierarquia de classes Java
Eu criei um AccountDemo
classe de aplicativo que permite experimentar o Account
hierarquia de classes. Primeiro, dê uma olhada AccountDemo
código-fonte de.
Listagem 5. AccountDemo
demonstra a hierarquia de classes de conta
class AccountDemo
{
public static void main(String() args)
{
SavingsAccount sa = new SavingsAccount(10000);
System.out.println("account name: " + sa.getName());
System.out.println("initial amount: " + sa.getAmount());
sa.deposit(5000);
System.out.println("new amount after deposit: " + sa.getAmount());
CheckingAccount ca = new CheckingAccount(20000);
System.out.println("account name: " + ca.getName());
System.out.println("initial amount: " + ca.getAmount());
ca.deposit(6000);
System.out.println("new amount after deposit: " + ca.getAmount());
ca.withdraw(3000);
System.out.println("new amount after withdrawal: " + ca.getAmount());
}
}
O main()
método na Listagem 5 demonstra primeiro SavingsAccount
então CheckingAccount
. Supondo Account.java
, SavingsAccount.java
, CheckingAccount.java
e AccountDemo.java
arquivos de origem estão no mesmo diretório, execute um dos seguintes comandos para compilar todos esses arquivos de origem:
javac AccountDemo.java
javac *.java
Execute o seguinte comando para executar o aplicativo:
java AccountDemo
Você deve observar a seguinte saída:
account name: savings
initial amount: 10000
new amount after deposit: 15000
account name: checking
initial amount: 20000
new amount after deposit: 26000
new amount after withdrawal: 23000
Substituição de método vs. sobrecarga de método
Uma subclasse pode sobrepor (substituir) um método herdado para que a versão do método da subclasse seja chamada. Um método de substituição deve especificar o mesmo nome, lista de parâmetros e tipo de retorno que o método que está sendo substituído. Para demonstrar, declarei um print()
método no Vehicle
classe, mostrada na Listagem 6.