La herencia es un concepto importante en la orientación a objetos. La herencia es otra forma importante de mejorar la reutilización del código además de la composición. Vimos en la composición que la composición es la interfaz funcional de un objeto que se llama repetidamente. Como veremos, la herencia le permite reutilizar definiciones de clases existentes.
herencia de clase
Cuando definimos una clase antes, comenzamos desde cero y definimos cada miembro de la clase en detalle. Por ejemplo, la siguiente clase Humana:
Copie el código de código de la siguiente manera:
claseHumano
{
/**
*accesor
*/
público int getHeight()
{
devolver esta altura;
}
/**
* mutador
*/
altura de crecimiento del vacío público (int h)
{
esta.altura = esta.altura + h;
}
/**
*aliento
*/
aliento vacío público ()
{
System.out.println("hu...hu...");
}
altura interna privada;
}
A partir de la definición de clase anterior, podemos comprender todos los detalles de la clase: los miembros de datos de la clase, los métodos de la clase y la interfaz de la clase.
Ahora necesitamos definir una nueva clase, como la clase Mujer, y asumir que la clase Mujer es bastante similar a la clase Humano:
Humano y Mujer
Podemos empezar desde cero y definir completamente la clase Mujer como antes:
Copie el código de código de la siguiente manera:
clase mujer
{
/**
*accesor
*/
público int getHeight()
{
devolver esta altura;
}
/**
* mutador
*/
altura de crecimiento del vacío público (int h)
{
esta.altura = esta.altura + h;
}
/**
*aliento
*/
aliento vacío público ()
{
System.out.println("hu...hu...");
}
/**
* nuevo método
*/
nacimiento humano público ()
{
System.out.println("Dar a luz");
retorno (nuevo Humano (20));
}
altura interna privada;
}
Un programador tendrá muchos problemas al escribir el programa anterior. Se han escrito muchas definiciones en la clase Humano, pero tenemos que escribirlas nuevamente. La clase Mujer solo agrega un nuevo método GiveBirth() (este método crea y devuelve un nuevo objeto Humano).
Usando la herencia, podemos evitar la duplicación anterior. Deje que la clase Mujer herede de la clase Humana, y la clase Mujer automáticamente tendrá las funciones de todos los miembros públicos de la clase Humana.
Usamos la palabra clave extends para indicar herencia:
Copie el código de código de la siguiente manera:
clase Mujer extiende Humano
{
/**
* nuevo método
*/
nacimiento humano público ()
{
System.out.println("Dar a luz");
retorno (nuevo Humano (20));
}
}
De esta forma nos ahorramos mucho tecleo. Mediante herencia, creamos una nueva clase, llamada clase derivada. La clase heredada (Humana) se llama clase base (clase base). La clase derivada utiliza la clase base como base para su propia definición y complementa el método GiveBirth() que no está definido en la clase base. La relación de herencia se puede expresar como:
Herencia: la flecha apunta a la clase base
Puede utilizar la siguiente clase de prueba para realizar pruebas:
Copie el código de código de la siguiente manera:
prueba de clase pública
{
principal vacío estático público (String [] argumentos)
{
Mujer aMujer = nueva Mujer();
una Mujer.growHeight(120);
System.out.println(aWoman.getHeight());
}
}
capa derivada
Mediante herencia, creamos la clase Mujer. Todo el proceso se puede dividir en tres niveles: definición de clase base, definición de clase derivada y uso externo.
El nivel de definición de clase base es definir una clase normalmente, como la definición de clase Humana anterior.
Desde la perspectiva de los usuarios externos (como un objeto de clase Mujer creado en la clase Prueba), la clase derivada tiene una interfaz externa unificada:
Para usuarios externos, la interfaz anterior es suficiente. Solo desde la perspectiva de la interfaz, no hay nada especial en las clases derivadas.
Sin embargo, los programadores deben tener cuidado al trabajar en el nivel de definiciones de clases derivadas:
Primero, la interfaz es mixta: los métodos getHeight() y growHeight() provienen de la clase base, mientras que el método GiveBirth() se define dentro de la clase derivada.
Hay más complicaciones. Anteriormente hemos podido acceder libremente a los miembros de la clase dentro de la clase (usando esto para referirnos al objeto). Sin embargo, cuando estamos dentro del alcance de la definición de la clase Mujer, no podemos acceder a los miembros privados de la clase base Humano. Recordamos el significado de privado: los miembros privados son sólo para uso interno de la clase. La clase Mujer es una clase nueva diferente de la clase Humana, por lo que se encuentra fuera de la clase Humana. En una clase derivada, no se puede acceder a los miembros privados de la clase base.
Pero lo interesante es que nuestros métodos growHeight() y getHeight() todavía funcionan. Esto muestra que los miembros privados de la clase base existen, pero no podemos acceder a ellos directamente.
Para aclarar el concepto, necesitamos comprender el mecanismo de generación de objetos de clase derivados. Cuando creamos un objeto de una clase derivada, Java en realidad crea primero un objeto de clase base (subobjeto) y agrega Los otros miembros definidos por la clase derivada constituyen un objeto de clase derivada. Lo que los usuarios externos pueden ver son los miembros públicos de la clase base y las clases derivadas. Como se muestra a continuación:
Objetos de clase base y objetos de clase derivada
El color amarillo en la imagen es el objeto de clase base. Los miembros de la capa base pueden acceder entre sí (use esto en la definición de clase Humana para referirse al objeto de clase base).
La parte azul es el nuevo contenido del objeto derivado. A esta parte la llamo capa derivada. Las partes azul y amarilla juntas forman el objeto derivado. Los miembros de la capa derivada pueden acceder entre sí (esto en la definición de Mujer). Además, también podemos acceder a los miembros públicos de la capa base. Por esta razón, usamos la palabra clave super para referirnos al objeto de clase base y usamos super.member para representar los miembros base (públicos).
Cuando estamos en la capa derivada (es decir, al definir la clase Mujer), no podemos acceder a los miembros privados de la base roja. Cuando estamos afuera, no podemos acceder ni a los miembros privados de la capa derivada púrpura ni a los miembros privados de la capa base roja.
(Los miembros privados de la capa derivada tienen restricciones de acceso, por lo que están marcados con una barra diagonal. Los miembros privados de la capa base tienen la mayor cantidad de restricciones de acceso, por lo que están marcados con una barra diagonal)
Super es similar a esto y también es un parámetro implícito. Cuando estemos en diferentes niveles de definición de clase, esto tendrá diferentes significados. Tenga cuidado con las palabras clave this y super.
(Java no obliga al uso de this y super. Java puede identificar automáticamente la propiedad de los miembros en muchos casos. Pero creo que es una buena práctica).
protegido
Anteriormente introdujimos dos palabras clave relacionadas con los permisos de acceso, privado y público, que controlan la visibilidad externa de los miembros. Ahora introducimos una nueva palabra clave de acceso: protegida.
Los miembros marcados como protegidos son visibles en esta clase y sus clases derivadas. Este concepto es fácil de entender, es decir, la capa derivada puede acceder a los miembros protegidos de la clase base, pero no desde el exterior, como se muestra a continuación:
anulación de método
La interfaz externa del objeto de clase derivada se compone en última instancia de los miembros públicos del objeto de clase base y los miembros públicos de la capa derivada. Si los miembros públicos de la clase base y los miembros públicos de la capa derivada tienen el mismo nombre, ¿cuál se muestra en la interfaz Java?
Ya hemos mencionado en constructores y sobrecarga de métodos que Java usa tanto el nombre del método como la lista de parámetros para determinar el método que se llamará. Un método está determinado por el nombre del método y la lista de parámetros. En el problema anterior, si solo los nombres de los métodos son iguales pero las listas de parámetros son diferentes, entonces los dos métodos se presentarán en la interfaz al mismo tiempo, lo que no nos causará ningún problema. Al realizar una llamada externa, Java decidirá qué método utilizar (sobrecarga de método) en función de los parámetros proporcionados.
¿Qué pasa si el nombre del método y la lista de parámetros son iguales? Al derivar la capa, también podemos usar super y this para determinar qué método es. Cuando es externo, solo presentamos una interfaz unificada, por lo que no podemos proporcionar dos métodos al mismo tiempo. En este caso, Java representará los métodos de la capa derivada en lugar de los métodos de la capa base.
Este mecanismo se llama anulación de método. Las anulaciones de métodos se pueden utilizar para modificar métodos de miembros de la clase base. Por ejemplo, en la capa derivada, es decir, al definir Mujer, puedes modificar el método Breath() proporcionado por la clase base:
Copie el código de código de la siguiente manera:
clase Mujer extiende Humano
{/**
* nuevo método
*/
nacimiento humano público ()
{
System.out.println("Dar a luz");
retorno (nuevo Humano (20));
}
/**
* anular Human.breath()
*/
aliento vacío público ()
{
super.aliento();
System.out.println("su...");
}
}
Tenga en cuenta que estamos en la capa derivada en este momento y aún podemos llamar al método Breath () del objeto de clase base a través de Super. Cuando llamamos a la clase Mujer externamente, debido a la anulación del método, ya no podemos llamar al método del objeto de la clase base.
La anulación de métodos mantiene la interfaz del objeto de clase base y utiliza la implementación de la capa derivada.
Constructor
Después de comprender los conceptos de objetos de clase base y capas derivadas, los métodos de construcción de clases derivadas son más fáciles de entender.
Necesitamos definir un constructor con el mismo nombre que la clase en la definición de la clase derivada. En este constructor:
1. Dado que el objeto de clase base se crea e inicializa primero al crear un objeto derivado, primero se debe llamar al constructor de la clase base. Podemos usar la declaración super(lista de argumentos) para llamar al constructor de la clase base.
2. Después de crear el objeto de clase base, comience a construir la capa derivada (inicializando los miembros de la capa derivada). Este es el mismo que el método de construcción general, consulte el método de construcción y la sobrecarga del método.
Por ejemplo, en el siguiente programa, la clase Humano tiene un constructor:
Copie el código de código de la siguiente manera:
claseHumano
{
/**
* constructor
*/
humano público (int h)
{
esta.altura = h;
}
/**
*accesor
*/
público int getHeight()
{
devolver esta altura;
}
/**
* mutador
*/
altura de crecimiento del vacío público (int h)
{
esta.altura = esta.altura + h;
}
/**
*aliento
*/
aliento vacío público ()
{
System.out.println("hu...hu...");
}
altura interna privada;
}
La definición de la clase derivada Clase Mujer y su método de construcción:
Copie el código de código de la siguiente manera:
clase Mujer extiende Humano
{
/**
* constructor
*/
Mujer pública (int h)
{
super(h); // constructor de clase base
System.out.println("¡Hola, Pandora!");
}
/**
* nuevo método
*/
nacimiento humano público ()
{
System.out.println("Dar a luz");
retorno (nuevo Humano (20));
}
/**
* anular Human.breath()
*/
aliento vacío público ()
{
super.aliento();
System.out.println("su...");
}
}
Resumir
se extiende
anulación del método
protegido
super.miembro, super()