Herança em Java é um dos conceitos fundamentais da Programação Orientada a Objetos. A herança em Java é usada quando temos uma relação é-um entre objetos. A herança em Java é implementada usando a palavra-chave extends
.
Herança em Java
A herança em Java é o método para criar uma hierarquia entre classes, herdando de outras classes.
A herança em Java é transitiva – então, se Sedan estende Carro e Carro estende Veículo, então Sedan também é herdado da classe Veículo. O Veículo se torna a superclasse tanto de Carro quanto de Sedan.
A herança é amplamente utilizada em aplicações Java, por exemplo, estendendo a classe Exceção para criar uma classe de Exceção específica da aplicação que contém mais informações, como códigos de erro. Por exemplo, NullPointerException.
Exemplo de Herança em Java
Cada classe em Java estende implicitamente a classe java.lang.Object
. Portanto, a classe Object está no topo da hierarquia de herança em Java.
Vamos ver como implementar herança em Java com um exemplo simples.
Superclasse: Animal
package com.journaldev.inheritance;
public class Animal {
private boolean vegetarian;
private String eats;
private int noOfLegs;
public Animal(){}
public Animal(boolean veg, String food, int legs){
this.vegetarian = veg;
this.eats = food;
this.noOfLegs = legs;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public String getEats() {
return eats;
}
public void setEats(String eats) {
this.eats = eats;
}
public int getNoOfLegs() {
return noOfLegs;
}
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
A classe Animal é a classe base aqui. Vamos criar uma classe Cat que herda da classe Animal.
Subclasse: Cat
package com.journaldev.inheritance;
public class Cat extends Animal{
private String color;
public Cat(boolean veg, String food, int legs) {
super(veg, food, legs);
this.color="White";
}
public Cat(boolean veg, String food, int legs, String color){
super(veg, food, legs);
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
Observe que estamos usando a palavra-chave extends
para implementar a herança em Java.
Programa de Teste de Herança em Java
Vamos escrever uma classe de teste simples para criar um objeto Cat e usar alguns de seus métodos.
package com.journaldev.inheritance;
public class AnimalInheritanceTest {
public static void main(String[] args) {
Cat cat = new Cat(false, "milk", 4, "black");
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat eats " + cat.getEats());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
System.out.println("Cat color is " + cat.getColor());
}
}
Saída:
A classe Cat não tem o método getEats()
, mas mesmo assim o programa funciona porque é herdado da classe Animal.
Pontos Importantes
-
A reutilização de código é o benefício mais importante da herança, pois as subclasses herdam as variáveis e métodos da superclasse.
-
Membros privados da superclasse não são diretamente acessíveis à subclasse. Como neste exemplo, a variável Animal noOfLegs não é acessível à classe Cat, mas pode ser indiretamente acessada por meio de métodos getter e setter.
-
Os membros da superclasse com acesso padrão são acessíveis à subclasse APENAS se estiverem no mesmo pacote.
-
Os constructores da superclasse não são herdados pela subclasse.
-
Se a superclasse não tiver um construtor padrão, então a subclasse também precisa ter um construtor explícito definido. Caso contrário, lançará uma exceção de tempo de compilação. No construtor da subclasse, a chamada para o construtor da superclasse é obrigatória neste caso e deve ser a primeira instrução no construtor da subclasse.
-
O Java não suporta herança múltipla, uma subclasse pode estender apenas uma classe. A classe Animal está implicitamente estendendo a classe Object e a classe Cat está estendendo a classe Animal, mas devido à natureza transitiva da herança em Java, a classe Cat também estende a classe Object.
-
Pode-se criar uma instância da subclasse e atribuí-la a uma variável da superclasse, isso é chamado de upcasting. Abaixo está um exemplo simples de upcasting:
Cat c = new Cat(); //instância da subclasse Animal a = c; //upcasting, tudo bem, já que Cat também é um Animal
-
Quando uma instância de Superclasse é atribuída a uma variável de Subclasse, então é chamado de downcasting. Precisamos fazer uma conversão explícita para Subclasse. Por exemplo;
Gato g = new Gato(); Animal a = g; Gato g1 = (Gato) a; //casting explícito, funciona bem porque "g" é realmente do tipo Gato
Observe que o compilador não reclamará mesmo se estivermos fazendo isso de maneira errada, devido à conversão explícita. Abaixo estão alguns casos em que lançará uma
ClassCastException
em tempo de execução.Cachorro c = new Cachorro(); Animal a = c; Gato g1 = (Gato) a; //ClassCastException em tempo de execução Animal a1 = new Animal(); Gato g2 = (Gato) a1; //ClassCastException porque a1 é realmente do tipo Animal em tempo de execução
-
Podemos substituir o método da Superclasse na Subclasse. No entanto, devemos sempre anotar o método substituído com @Override. O compilador saberá que estamos substituindo um método e se algo mudar no método da superclasse, receberemos um erro de tempo de compilação em vez de obter resultados indesejados em tempo de execução.
-
Podemos chamar os métodos da superclasse e acessar as variáveis da superclasse usando a palavra-chave super. Isso é útil quando temos uma variável/método com o mesmo nome na subclasse, mas queremos acessar a variável/método da superclasse. Também é usado quando construtores são definidos na superclasse e subclasse, e precisamos chamar explicitamente o construtor da superclasse.
-
Pode-se usar a instrução
instanceof
para verificar a herança entre objetos, veja o exemplo abaixo.
```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;
boolean flag = c instanceof Cat; //normal case, returns true
flag = c instanceof Animal; // returns true since c is-an Animal too
flag = an instanceof Cat; //returns true because a is of type Cat at runtime
flag = an instanceof Dog; //returns false for obvious reasons.
```
- Não é possível estender classes Finais em Java.
- Se você não pretende utilizar a Superclasse no código, ou seja, se a sua Superclasse é apenas uma base para manter código reutilizável, então você pode mantê-las como Classe Abstrata para evitar uma instanciação desnecessária por parte das classes clientes. Isso também restringirá a criação de instâncias da classe base.
Tutorial em Vídeo sobre Herança em Java
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
Você pode conferir mais exemplos de herança em nosso Repositório no GitHub.
Referência: Documentação da Oracle
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example