Java es un lenguaje orientado a objetos. Esto significa que todo en Java consta de clases y sus objetos, y obedece a los paradigmas de la POO (programación orientada a objetos). Uno de esos paradigmas es la herencia, un mecanismo en Java mediante el cual se permite a una clase heredar las características (campos y métodos) de otra clase. En pocas palabras, en Java, la herencia significa crear nuevas clases basadas en las existentes.
Actores clave de la herencia en Java
- La herencia es el concepto de que una clase puede repetir parcial o completamente las propiedades y métodos de su padre (la clase de la que hereda).
- Una clase hija, una subclase, una clase extendida o una clase derivada es una clase que hereda de otra clase.
- Una clase principal, superclase o clase base es una clase que tiene varias funciones, y estas funciones pueden ser pasadas (heredadas) por otra clase (clase secundaria).
- La anulación de métodos consiste en cambiar el comportamiento de un método de clase derivada. Suele ser un comportamiento más específico y refinado. Si anula un método en el heredero que ya está en la clase principal, en cierto modo reemplaza el método principal.
- Una clase puede tener sólo una clase ancestral, pero cada clase puede tener muchos "hijos".
Cómo funciona
La cadena de herencia se dirige desde la clase más abstracta a la más concreta. Es decir, la superclase es la más abstracta de la cadena de clases. A menudo se denota como abstracta (clase base que no requiere implementación). Todas las clases posteriores son más específicas. Por ejemplo, existe una clase llamada "Gadget". Puede tener un "peso" de campo (o estado), capacidad de la batería de campo, nivel de carga de campo y métodos (o comportamiento) de "trabajo" y carga. En este caso, los métodos pueden ser abstractos, es decir, no tienen una implementación específica. Si bien no podemos decir qué tipo de dispositivo es, es absolutamente cualquier dispositivo recargable. Creemos una subclase de Teléfono de la clase Gadget. Ya no necesita redefinir el peso y la batería, simplemente los hereda del gadget abstracto. Pero será necesario aclarar el comportamiento de la obra. También puedes agregar otros campos “diagonal de pantalla”, conectores, etc. Puede agregar un nuevo método "Actualizar sistema operativo". A continuación, podemos crear dos clases más y ambas se heredarán de Phone, Android y iPhone. Ambas clases heredan todos los campos y métodos del Gadget y del Smartphone, y los métodos se pueden anular. La primera clase necesita el campo "Marca", mientras que el iPhone no necesita este campo, ya que sólo una empresa produce este tipo de teléfonos inteligentes.class Gadget {
…
}
}
//subclass of Gadget class
class Phone extends Gadget {
…
}
//subclass of Phone class
class IPhone extends Phone {
…
}
//subclass of Phone class
class AndroidPhone extends Phone {
…
}
Una clase secundaria hereda todos los miembros públicos y protegidos de la clase principal. No importa en qué paquete se encuentre la subclase. Si la clase secundaria está en el mismo paquete que la clase principal, también hereda los miembros privados del paquete principal. Puede utilizar miembros heredados tal cual, reemplazarlos, ocultarlos o agregar nuevos miembros:
- Puede utilizar campos heredados directamente, como cualquier otro campo.
- Puede declarar un campo en la clase secundaria que tenga el mismo nombre que en la clase principal. Lo está ocultando (así que mejor no hacerlo).
- Puede declarar nuevos campos en la clase secundaria (los que la clase principal no tiene).
- Los métodos heredados se pueden utilizar directamente sin anularlos en la clase derivada.
- También puede escribir un nuevo método de instancia en una subclase que tenga la misma firma que un método en la clase principal. Este procedimiento lo anula.
- Puede declarar nuevos métodos en la clase secundaria que no fueron declarados en la clase principal.
- Puede escribir un constructor de subclase que llame al constructor de superclase implícitamente o con la palabra clave super.
Ejemplo
Creemos una clase base MusicalInstrument con campos de peso y marca registrada, así como un método work() . También definimos un constructor.public class MusicalInstrument {
int weight;
String tradeMark;
public MusicalInstrument(int weight, String tradeMark) {
this.weight = weight;
this.tradeMark = tradeMark;
}
public void work() {
System.out.println("the instrument is playing...");
}
}
No está del todo claro qué tipo de instrumento musical es y cómo tocarlo. Creemos un instrumento más específico, el violín. Tendrá los mismos campos que en el Instrumento Musical (se llamarán en el constructor usando la palabra clave super. También podemos anular el método de trabajo y crear un método para configurar el violín cuerda por cuerda.
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
@Override
public void work() {
System.out.println("THe violin's playing");
}
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
Creemos una clase de demostración para probar la clase Violín y ver exactamente cómo funciona la herencia.
public class InheritDemo {
public static void main(String[] args) {
Violin violin = new Violin(1, null, "Amati", "Kremer", 285, false);
violin.violinTuning();
violin.work();
}
}
En este caso, la salida del programa será la siguiente:
Estoy afinando la primera cuerda... Estoy afinando la segunda cuerda... Estoy afinando la tercera cuerda... Estoy afinando la cuarta cuerda... El violín está tocando
Es decir, si hay un método anulado en la clase secundaria, ya no se llamará al método ancestro. ¿Qué pasa si no está allí? Es decir, la clase Violín se ve así:
public class Violin extends MusicalInstrument {
String master;
String owner;
int age;
boolean isTuned;
public Violin(int weight, String tradeMark, String master, String owner, int age, boolean isTuned) {
super(weight, tradeMark);
this.master = master;
this.owner = owner;
this.age = age;
this.isTuned = isTuned;
}
// @Override
// }
public void violinTuning () {
System.out.println("I'm tuning 1st string...");
System.out.println("I'm tuning 2nd string...");
System.out.println("I'm tuning 3rd string...");
System.out.println("I'm tuning 4th string...");
}
}
La salida es:
Estoy afinando la primera cuerda... Estoy afinando la segunda cuerda... Estoy afinando la tercera cuerda... Estoy afinando la cuarta cuerda... el instrumento está tocando...
Es decir, se llamará automáticamente al método ancestro. Por cierto, la clase secundaria se puede definir a través del ancestro, es decir, para realizar upcasting:
Parent parent = new Child()
Esta inicialización se utiliza para acceder solo a los miembros presentes en la clase principal y a los métodos anulados. En nuestro ejemplo sería:
public class InheritDemo {
public static void main(String[] args) {
MusicalInstrument violin = new Violin(1, null, "Amati", "Kremer", 285, false);
//violin.violinTuning();
violin.work();
}
}
En tal caso, no podremos configurar el método del violín. Sin embargo, al mismo tiempo, se llamará al método work() de la clase descendiente, si existe.
La jerarquía de clases de la plataforma Java
En Java todo está formado por clases y están subordinadas a una jerarquía. Surge la pregunta: ¿existe una clase de la que se heredan todas las demás? La respuesta es sí, de hecho esa clase existe. Y se llama simplemente Objeto . La clase Object del paquete java.lang define e implementa el comportamiento común a todas las clases, incluidas las que usted crea. En la plataforma Java, muchas clases derivan directamente de Object , otras clases derivan de algunas de estas clases, y así sucesivamente, formando una jerarquía de clases.Tipos de herencia en Java
Resaltemos algunos tipos de herencia en Java. 1. Herencia única Este tipo es como en nuestro ejemplo anterior, las subclases heredan las características de una superclase. En la imagen siguiente, la clase A sirve como clase base para la clase derivada B. 2. Herencia multinivel Esto es solo una cadena de herencia, es decir, hay una clase base A, la clase B se hereda de ella y la clase C se hereda de la clase B. En Java, una clase no puede acceder directamente a los miembros del abuelo. 3. Herencia jerárquica En la herencia jerárquica, una clase sirve como superclase (clase base) para más de una subclase. Arriba, dimos un ejemplo de la clase Teléfono, que puede tener dos "hijos": AndroidPhone y IPhone.class A {
public void printA() {
System.out.println("A");
}
}
class B extends A {
public void printB() {
System.out.println(" B"); }
}
class C extends A {
public void printC() {
System.out.println("C");
}
}
class D extends A {
public void printD() {
System.out.println("D");
}
}
public class Demo {
public static void main(String[] args)
{
B objB = new B();
objB.printA();
objB.printB();
C objC = new C();
objC.printA();
objC.printC();
D objD = new D();
objD.printA();
objD.printD();
}
}
La salida es:
A B A C A D
4. Herencia múltiple, es decir, la presencia de varios ancestros... pero espera, la herencia múltiple clásica no es compatible con Java. Hasta cierto punto, se puede implementar no utilizando clases, sino interfaces.
interface A {
public void printA();
}
interface B {
public void printB();
}
interface C extends A, B {
public void print();
}
class InheritDemo implements C {
@Override
public void print()
{
System.out.println("Print something");
}
@Override
public void printA() {
}
@Override
public void printB() {
}
}
GO TO FULL VERSION