La herencia en Java es uno de los conceptos fundamentales de la Programación Orientada a Objetos. La herencia en Java se utiliza cuando tenemos una relación es-un entre objetos. La herencia en Java se implementa utilizando la palabra clave extends
.
Herencia en Java
La herencia en Java es el método para crear una jerarquía entre clases al heredar de otras clases.
La herencia en Java es transitiva, por lo que si Sedan extiende Carro y Carro extiende Vehículo, entonces Sedan también hereda de la clase Vehículo. El Vehículo se convierte en la superclase tanto de Carro como de Sedan.
La herencia se usa ampliamente en aplicaciones Java, por ejemplo, extendiendo la clase Exception para crear una clase de Excepción específica de la aplicación que contiene más información como códigos de error. Por ejemplo, NullPointerException.
Ejemplo de Herencia en Java
Cada clase en Java extiende implícitamente la clase java.lang.Object
. Por lo tanto, la clase Object está en el nivel superior de la jerarquía de herencia en Java.
Veamos cómo implementar la herencia en Java con un ejemplo simple.
Superclase: 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;
}
}
El Animal es la clase base aquí. Creemos una clase Cat que herede de la clase Animal.
Subclase: 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;
}
}
Observa que estamos utilizando la palabra clave extends
para implementar la herencia en Java.
Programa de Prueba de Herencia en Java
Escribamos una clase de prueba simple para crear un objeto Cat y utilizar algunos de sus 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());
}
}
Salida:
La clase Cat no tiene el método getEats()
, pero aún así, el programa funciona porque se hereda de la clase Animal.
Puntos Importantes
-
La reutilización de código es el beneficio más importante de la herencia, ya que las subclases heredan las variables y métodos de la superclase.
-
Los miembros privados de la superclase no son directamente accesibles para la subclase. En este ejemplo, la variable Animal noOfLegs no es accesible para la clase Cat, pero puede ser accesible de manera indirecta a través de los métodos getter y setter.
-
Los miembros de la superclase con acceso predeterminado son accesibles para la subclase ÚNICAMENTE si están en el mismo paquete.
-
Los constructores de la superclase no son heredados por la subclase.
-
Si la superclase no tiene un constructor predeterminado, entonces la subclase también necesita tener un constructor explícito definido. De lo contrario, generará una excepción en tiempo de compilación. En el constructor de la subclase, la llamada al constructor de la superclase es obligatoria en este caso y debe ser la primera instrucción en el constructor de la subclase.
-
Java no admite la herencia múltiple, una subclase solo puede extender una clase. La clase Animal está implicitamente extendiendo la clase Object y la clase Cat está extendiendo la clase Animal, pero debido a la naturaleza transitoria de la herencia en Java, la clase Cat también extiende la clase Object.
-
Podemos crear una instancia de una subclase y luego asignarla a una variable de superclase, esto se llama upcasting. A continuación, se muestra un ejemplo simple de upcasting:
Cat c = new Cat(); // instancia de la subclase Animal a = c; // upcasting, está bien ya que Cat también es un Animal
-
Cuando una instancia de la Superclase se asigna a una variable de Subclase, se llama downcasting. Necesitamos hacer un casting explícito a Subclase. Por ejemplo;
Cat c = new Cat(); Animal a = c; Cat c1 = (Cat) a; //casting explícito, funciona bien porque "c" es realmente de tipo Cat
Nota que el compilador no se quejará incluso si lo estamos haciendo incorrectamente, debido al casting explícito. A continuación, se presentan algunos casos en los que lanzará una
ClassCastException
en tiempo de ejecución.Dog d = new Dog(); Animal a = d; Cat c1 = (Cat) a; //ClassCastException en tiempo de ejecución Animal a1 = new Animal(); Cat c2 = (Cat) a1; //ClassCastException porque a1 es realmente de tipo Animal en tiempo de ejecución
-
Podemos anular el método de la Superclase en la Subclase. Sin embargo, siempre debemos anotar el método anulado con @Override. El compilador sabrá que estamos anulando un método y si algo cambia en el método de la superclase, obtendremos un error en tiempo de compilación en lugar de obtener resultados no deseados en tiempo de ejecución.
-
Podemos llamar a los métodos de la superclase y acceder a las variables de la superclase usando la palabra clave super. Viene bien cuando tenemos una variable/método con el mismo nombre en la subclase pero queremos acceder a la variable/método de la superclase. También se usa cuando se definen Constructores en la superclase y subclase y tenemos que llamar explícitamente al constructor de la superclase.
-
Podemos usar la instrucción
instanceof
para verificar la herencia entre objetos, veamos esto con el siguiente ejemplo.
```
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.
```
- No podemos extender clases Finales en Java.
- Si no vas a utilizar la Superclase en el código, es decir, si tu Superclase es simplemente una base para mantener código reutilizable, entonces puedes mantenerlas como clase abstracta para evitar instanciaciones innecesarias por parte de las clases cliente. También restringirá la creación de instancias de la clase base.
Tutorial en Video sobre Herencia en Java
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
Puedes consultar más ejemplos de herencia en nuestro Repositorio de GitHub.
Referencia: Documentación de Oracle
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example