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 de é-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 ao herdar de outras classes.
A herança em Java é transitiva – então, se Sedan estende Car e Car estende Vehicle, então Sedan também é herdado da classe Vehicle. O Vehicle se torna a superclasse tanto de Car quanto de Sedan.
A herança é amplamente utilizada em aplicações Java, por exemplo, estendendo a classe Exception 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 a 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;
}
}
O Animal é a classe base aqui. Vamos criar uma classe Gato que herda da classe Animal.
Subclasse: Gato
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 Gato 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 Gato não possui 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.
-
Os 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 Gato, mas pode ser acessada indiretamente por meio dos métodos getter e setter.
-
Os membros da superclasse com acesso padrão são acessíveis à subclasse SOMENTE se estiverem no mesmo pacote.
-
Os construtores 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 ao construtor da superclasse é obrigatória neste caso e deve ser a primeira declaraçã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, está 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 c = new gato(); Animal a = c; gato c1 = (gato) a; //casting explícito, funciona bem porque "c" é realmente do tipo gato
Observe que o compilador não reclamará mesmo se estivermos fazendo isso errado, devido à conversão explícita. Abaixo estão alguns casos em que ele lançará uma
ClassCastException
em tempo de execução.cachorro d = new cachorro(); Animal a = d; gato c1 = (gato) a; //ClassCastException em tempo de execução Animal a1 = new Animal(); gato c2 = (gato) a1; //ClassCastException porque a1 é realmente do tipo Animal em tempo de execução
-
Pode-se substituir o método da Superclasse na Subclasse. No entanto, devemos sempre anotar o método substituído com @Override annotation. 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. Isso também é usado quando Construtores são definidos na superclasse e na subclasse e temos que chamar explicitamente o construtor da superclasse.
-
Podemos usar a instrução
instanceof
para verificar a herança entre objetos, vamos ver isso com 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 podemos estender classes Final em java.
- Se você não vai usar Superclasse no código, ou seja, sua Superclasse é apenas uma base para manter código reutilizável, então você pode mantê-los como Classe Abstrata para evitar instanciação desnecessária pelas classes clientes. Isso também restringirá a criação de instância 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 do GitHub.
Referência: Documentação da Oracle
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example