Contenido
- ¿Qué es la herencia?
- ¿Cuáles son los beneficios de la herencia?
- Características de la herencia
- Consideraciones al usar la herencia
- ¿Cuál es la diferencia entre super y this?
- Reescritura de métodos (anulación)
- Palabra clave final
- Polimorfismo
- Abstracción (abstract)
- Clases internas
- Contenido modificado por diferentes modificadores (no relacionado con clases internas)
- Cuatro modificadores de acceso
¿Qué es la herencia?
Cuando varias clases tienen los mismos atributos y comportamientos, se extraen estos contenidos en una clase separada. Entonces, las múltiples clases no necesitan volver a definir estos atributos y comportamientos, solo necesitan heredar de esa clase.
Las múltiples clases pueden llamarsesubclases, y esta clase separada se llamaclase padre、superclaseoclase base。
Las subclases pueden acceder directamente a losno privadosatributos y comportamientos de la clase padre.
A través de laextendspalabra clave se establece una relación de herencia entre clases.
class SubDemo extends Demo{} //SubDemo是子类,Demo是父类
¿Cuáles son los beneficios de la herencia?
- Mejorar lareutilización del código。
- Hace que las clases tengan relación entre sí, es elprerrequisito del polimorfismo。
Características de la herencia
1. Java solo admite herencia única, no admite herencia múltiple.
//一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error
2. Java admite herencia multinivel (en cadena) (sistema de herencia).
class A{}
class B extends A{}
class C extends B{}
Consideraciones al usar la herencia
- Si entre las clases existe una relación "is a" (es un), se puede considerar usar herencia.
- No uses herencia solo para heredar parte de las funcionalidades.
¿Cuál es la diferencia entre super y this?
superEs una palabra clave que representa elidentificador del espacio de almacenamiento. (Puede entenderse como la referencia del padre).
El uso de super y this es similar.
this representa lareferencia al objeto(quien lo llama, lo representa);
super representala subclase actualSobrela clase padrede la referencia.
Escenarios de uso
- Cuando la clase padre y la subclase tienen miembros con el mismo nombre, se puede usar super para distinguirlos;
- Cuando la subclase necesita llamar al constructor de la clase padre, se puede usar la sentencia super.
Diferencias
1. Variables miembro
this.变量 -- 本类的 super.变量 -- 父类的
2. Constructores
this(...) -- 本类的 super(...) -- 父类的
3. Métodos miembro
this.方法名() -- 本类的 super.方法名() -- 父类的
super(); y this(); deben estar en la primera línea del constructor y no pueden aparecer al mismo tiempo.
Reescritura de métodos (anulación)
Cuando en la subclase aparece un método idéntico al de la clase padre (excepto el modificador de acceso; el modificador de acceso debe ser mayor o igual y no incluye private; el tipo de retorno, el nombre del método y la lista de parámetros son iguales), se produce una anulación, también llamada reescritura o sobreescritura.
Los métodos privados de la clase padre no son visibles para la subclase, por lo que no se puede hablar de anular los métodos privados de la clase padre.
Precauciones al anular:
- Al anular, el permiso del método de la subclase debe ser mayor o igual que el permiso del método de la clase padre;
- Un método estático solo puede anular a un método estático.
Escenarios de uso de la anulación:
Cuando la subclase necesita la funcionalidad de la clase padre, pero el cuerpo de la funcionalidad tiene contenido específico de la subclase, se puede sobrescribir el método de la clase padre. Así, se hereda la funcionalidad de la clase padre y también se define el contenido específico de la subclase.
¿Cuál es la diferencia entre reescritura y sobrecarga de métodos??
La reescritura de métodos se usa cuando el método de la subclase es idéntico al de la clase padre; excepto el modificador de acceso, el tipo de retorno, el nombre del método y la lista de parámetros son todos iguales.
La sobrecarga se usa en el caso de que en la misma clase varios métodos tengan el mismo nombre pero diferente lista de parámetros (no tiene relación con el tipo de retorno).
Uso de los constructores en la clase padre y la subclase:
- Durante el proceso de inicialización de la subclase, primero se ejecuta la inicialización de la clase padre. Esto se debe a que el constructor de la subclase tiene un super() por defecto. Si la subclase va a usar las variables miembro de la clase padre, esta inicialización debe completarse antes de la inicialización de la subclase. Por lo tanto, durante la inicialización de la subclase, primero se ejecuta la inicialización de la clase padre.
- Si la clase padre no tiene constructor sin parámetros
- Usar super para llamar al constructor con parámetros de la clase padre. Es el método recomendado.
- Usar this para llamar a otros constructores de la propia clase.
Orden de ejecución de los bloques de código estáticos, bloques de código de construcción y constructores:
Bloque de código estático de la clase padre → Bloque de código estático de la subclase → Bloque de código de construcción de la clase padre → Constructor de la clase padre → Bloque de código de construcción de la subclase → Constructor de la subclase
Palabra clave final
final es una palabra clave que se puede usar para modificar clases, variables miembro y métodos miembro.
Características:
- La clase que modifica no puede ser heredada.
- La variable miembro que modifica es una constante.
- El método miembro que modifica no puede ser reescrito por la subclase.
Las constantes modificadas por final generalmente tienen una convención de escritura: el nombre de la constante modificada por final, todas sus letras deben estar enmayúsculas。
Cuando final modifica una variable miembro, debe inicializarse. Hay dos formas de inicialización:
- Inicialización explícita;
- Inicialización en el constructor.
Pero no se pueden inicializar las dos a la vez.
Diferencia entre final y private:
- La clase modificada por final puede ser accedida;
private no puede modificar clases externas, pero sí puede modificar clases internas (en realidad, hacer privada una clase externa no tiene sentido). - Los métodos modificados por final no pueden ser reescritos por la subclase;
Los métodos modificados por private, aparentemente pueden ser reescritos por la subclase, pero en realidad no pueden; la subclase no puede ver los métodos privados de la clase padre. - Las variables modificadas por final solo pueden asignarse una vez durante la inicialización explícita o la inicialización en el constructor; no se permite cambiarlas después.
Las variables modificadas por private tampoco permiten que la subclase u otras clases del mismo paquete accedan o modifiquen directamente, pero se pueden cambiar y obtener sus valores mediante los métodos set y get.
Polimorfismo
Concepto:
Los diferentes estados que muestra un objeto en diferentes momentos.
Prerrequisitos del polimorfismo:
- Debe haber una relación de herencia o implementación.
- Debe haber reescritura de métodos.
- Debe haber una referencia de la clase padre apuntando a un objeto de la subclase.
Manifestación en el programa:
La referencia de la clase padre o interfaz apunta o recibe su propioobjeto de subclase。
Beneficios y efectos:
La existencia del polimorfismo mejora laextensibilidady la posteriormantenibilidad。
Desventajas:
Cuando se llama con una referencia de la clase padre, solo se pueden llamar métodos de la clase padre, no los métodos específicos de la subclase, porque no sabes qué tipo de subclase te heredará en el futuro.
Características de los miembros en el polimorfismo:
- Variables miembro: En tiempo de compilación: se observa si la clase a la que pertenece la variable de tipo referencia tiene la variable llamada;
En tiempo de ejecución: también se observa si la clase a la que pertenece la variable de tipo referencia tiene la variable llamada.
Las variables miembro, tanto en compilación como en ejecución, dependen de la clase a la que pertenece la variable de tipo referencia. Para recordarlo de forma sencilla:Variables miembro: tanto en compilación como en ejecución, se mira el lado izquierdo del signo igual.。 - Métodos miembro: En tiempo de compilación: se debe verificar si la clase a la que pertenece la variable de referencia tiene el miembro llamado;
En tiempo de ejecución: se debe verificar si la clase a la que pertenece el objeto tiene el miembro llamado. Si la clase padre y la subclase tienen un método con el mismo nombre, se ejecutará el método de la subclase, porque los métodos tienen la característica de anulación.
En compilación se mira el lado izquierdo, en ejecución se mira el lado derecho.。 - Métodos estáticos: En tiempo de compilación: se observa si la clase a la que pertenece la variable de tipo referencia tiene la variable llamada;
En tiempo de ejecución: también se observa si la clase a la que pertenece la variable de tipo referencia tiene la variable llamada.
Tanto en compilación como en ejecución se mira el lado izquierdo del signo igual.。
¡Definitivamente no se puede convertir un objeto de la clase padre al tipo de la subclase!
La referencia de la clase padre apunta a un objeto de la subclase; esta referencia puede ser promovida, y también puede serconvertida forzosamente。
¡En el polimorfismo, de principio a fin, es el objeto de la subclase el que cambia!
//多态向下转型和向上转型的例子,多态转型解决了多态中父类引用不能使用子类特有成员的弊端。
class PolymorphicTest2 {
public static void main(String[] args) {
Phone p1 = new Nokia(); //向上转型,类型提升
Nokia no = (Nokia)p1; //向下转型,强制将父类的引用转换成子类类型,不能将Nokia类型转成Moto或Nexus类型
no.print(); //输出结果为Phone---null---0,因为继承了父类的方法
Phone p2 = new Moto();
Moto m = (Moto)p2;
m.print(); //输出结果为Moto---yellow---1599,方法重写,子类方法覆盖父类方法
Phone p3 = new Nexus();
Nexus ne = (Nexus)p3;
ne.print();
}
}
class Phone{
String color;
int price;
public void print(){
System.out.println("Phone---" + color + "---" + price );
}
}
class Nokia extends Phone{
String color = "red";
int price = 1009;
//public void print(){
// System.out.println("Nokia---" + color + "---" + price);
//}
}
class Moto extends Phone{
String color = "yellow";
int price = 1599;
public void print(){
System.out.println("Moto---" + color + "---" + price);
}
}
class Nexus extends Phone{
String color = "black";
int price = 1999;
public void print(){
System.out.println("Nexus---" + color + "---" + price);
}
}
}
Abstracción (abstract)
La abstracción consiste en extraer los contenidos comunes y esenciales de múltiples cosas.
Clase abstracta:
En Java se pueden definirmétodos sin cuerpodel método, la implementación específica de este método es proporcionada porSubclaseHecho, este método se denomina método abstracto; la clase que contiene métodos abstractos es una clase abstracta.
Origen:
Varios objetos tienen la misma funcionalidad, pero el contenido específico de la funcionalidad es diferente; en el proceso de extracción, solo se extrae la definición de la funcionalidad, no el cuerpo de la funcionalidad. Así, el método que solo tiene declaración de funcionalidad y no tiene cuerpo de funcionalidad se denomina método abstracto.
Características de la clase abstracta:
- Los métodos abstractos deben estar en una clase abstracta.
- Tanto los métodos abstractos como las clases abstractas deben modificarse con la palabra clave `abstract`.
- Las clases abstractas no pueden crear objetos con `new`, porque llamar a un método abstracto no tiene sentido.
- Para que los métodos abstractos de una clase abstracta puedan usarse, una subclase debe sobrescribir todos sus métodos abstractos y luego crear un objeto de la subclase para invocarlos. Si la subclase solo sobrescribe parte de los métodos abstractos, entonces dicha subclase sigue siendo una clase abstracta.
- Las clases abstractas pueden tener métodos abstractos y también métodos no abstractos; los métodos abstractos se utilizan para la instanciación de subclases.
- Si una clase es abstracta, entonces las subclases que la heredan deben ser abstractas o sobrescribir todos los métodos abstractos.
Especial: en una clase abstracta no es necesario definir métodos abstractos; esto se hace únicamente para impedir que se creen objetos de esa clase.
Características de los miembros de la clase abstracta:
- Variables miembro: pueden ser variables o constantes.
- Constructores: los hay.
- Métodos miembro: pueden ser abstractos o no abstractos.
abstract class 葵花宝典 {
public abstract void 自宫();
}
class 岳不群 extends 葵花宝典 {
public void 自宫(){
System.out.println("剪刀");
}
}
class 林平之 extends 葵花宝典{
public void 自宫(){
System.out.println("指甲刀");
}
}
class AbstractTest {
public static void main(String[] args) {
岳不群 岳 = new 岳不群();
岳.自宫();
林平之 林 = new 林平之();
林.自宫();
}
}
Notas sobre las clases abstractas:
Las clases abstractas no se pueden instanciar, ¿por qué tienen constructor??
Cualquier clase definida con `class` siempre tiene un constructor. Los constructores en la clase abstracta están destinados a la instanciación de las subclases.
Una clase no tiene métodos abstractos, ¿por qué se define como clase abstracta??
Cuando no se desea que sea heredada ni instanciada.
¿Con qué palabras clave no puede coexistir la palabra clave `abstract`??
- `final`: si un método es abstracto, debe ser sobrescrito, pero `final` no puede ser sobrescrito, por lo que hay conflicto.
- `private`: si el método es privado, la subclase no puede acceder directamente a él, ¿cómo podría sobrescribirlo?
- `static`: no se necesita un objeto; el nombre de la clase puede invocar el método abstracto. Pero invocar un método abstracto no tiene sentido.
Interfaz (`interface`)
InterfazSíMétodos abstractosyValores constantesLa colección de métodos abstractos y valores constantes. En esencia, la interfaz es una clase abstracta especial: este tipo de clase abstracta solo contiene definiciones de constantes y métodos, sin variables y sin implementación de métodos.
Formato:`interface NombreInterfaz {}`
La aparición de la interfaz refleja la "herencia múltiple" de otra forma, es decir, la "implementación múltiple".
Implementación (`implements`)
Formato:`class NombreClase implements NombreInterfaz {}`
Características:
- Las interfaces no se pueden instanciar.
- Si una clase implementa una interfaz, debe ser abstracta o implementar todos los métodos de la interfaz.
Características de los miembros de la interfaz:
¡Los modificadores de los miembros en una interfaz son fijos!
- Constantes miembro: `public static final`; las variables definidas en una interfaz son constantes globales, y los modificadores solo pueden ser estas tres palabras clave; todas pueden omitirse; los nombres de las constantes deben estar en mayúsculas.
- Métodos miembro: `public abstract`; todos los métodos definidos en una interfaz son abstractos, y las dos palabras clave modificadoras pueden omitirse.
- Recomendado: siempre proporcionar los modificadores manualmente.
Diferencia entre herencia e implementación:
- Entre clases se denomina relación de herencia: porque la clase, ya sea abstracta o no, puede definir métodos no abstractos en su interior, y estos métodos pueden ser usados directamente por las subclases con solo heredarlos. Solo se permite herencia única, pero puede haber herencia multinivel. ((class))
- Entre clases e interfaces es una relación de implementación: porque todos los métodos en una interfaz son abstractos, deben ser implementados por una subclase para poder instanciarla. Puede ser implementación única o múltiple; también se puede implementar múltiples interfaces mientras se hereda de una clase. ((class) extends (class) implements (interface1,interface2…))
- Entre interfaces es una relación de herencia: una interfaz puede heredar otra interfaz y agregar nuevos atributos y métodos abstractos, y las interfaces pueden tener herencia múltiple. ((interface) extends (interface1,interface2…))
Diferencias entre clase abstracta e interfaz:
Variables miembro
- La clase abstracta puede tener variables y también constantes.
- La interfaz solo puede tener constantes.
Métodos miembro
- La clase abstracta puede tener métodos no abstractos y también métodos abstractos.
- La interfaz solo puede tener métodos abstractos.
Constructores
La clase abstracta tiene constructores.
La interfaz no tiene constructores.
Relación entre clases, clases abstractas e interfaces
- La relación entre una clase y una clase abstracta es de herencia: `extends`.
- La relación entre una clase y una interfaz es de implementación: `implements`.
Características conceptuales de la interfaz:
- La interfaz esexpuesta al exteriorla regla;
- La interfaz es laextensión de funciones;
- La aparición de la interfazreduce el acoplamiento; (se logra un desarrollo modular: se definen reglas, cada persona implementa su propio módulo, lo que mejora en gran medida la eficiencia del desarrollo)
- La interfaz se puede usar paraimplementación múltiple;
- múltiplesClases no relacionadas pueden implementar la misma interfaz.
- Una clase puede implementarmúltiplesinterfaces que no tienen relación directa entre sí.
- De manera similar a la herencia, entre la interfaz y la clase que la implementa existepolimorfismo。
//运动员和教练的案例(下图是思路分析)
/*
篮球运动员和教练
乒乓球运动员和教练
现在篮球运动员和教练要出国访问,需要学习英语
请根据你所学的知识,分析出来哪些是类,哪些是抽象类,哪些是接口
*/
interface SpeakEnglish {
public abstract void speak();
}
interface GoAboard{
public abstract void aboard();
}
abstract class Person {
private String name;
private int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
//吃饭
public abstract void eat();
//睡觉
public void sleep(){
System.out.println("Zzz...");
}
}
//运动员
abstract class Player extends Person {
public abstract void study();
}
//教练
abstract class Coach extends Person {
public abstract void teach();
}
//篮球运动员
class BasketballPlayer extends Player implements SpeakEnglish,GoAboard{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡腿");
}
public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣篮");
}
public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello World");
}
public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓运动员
class PingPangPlayer extends Player{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋");
}
public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣球");
}
}
//篮球教练
class BasketballCoach extends Coach implements SpeakEnglish {
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "啃鸡爪");
}
public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣篮");
}
public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello Java");
}
public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓球教练
class PingPangCoach extends Coach{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋皮");
}
public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣球");
}
}
class PlayerAndCoach {
public static void main(String[] args) {
//篮球运动员
BasketballPlayer bp = new BasketballPlayer();
bp.setName("郭艾伦");
bp.setAge(33);
bp.eat();
bp.sleep();
bp.study();
bp.speak();
bp.aboard();
System.out.println("***********************");
//篮球教练
BasketballCoach bc = new BasketballCoach();
bc.setName("波波维奇");
bc.setAge(65);
bc.eat();
bc.sleep();
bc.teach();
bc.speak();
bc.aboard();
System.out.println("***********************");
//多态
Person p = new BasketballPlayer();
p.setName("Kobe Bryant");
p.setAge(33);
p.eat();
p.sleep();
//p.study();
//p.speak();
BasketballPlayer bp2 = (BasketballPlayer)p;
bp2.study();
bp2.speak();
bp2.aboard();
System.out.println("***********************");
}
}
Clases internas
Definir una clase dentro de otra clase; la clase que está dentro se llama clase interna. La aparición de la clase interna rompe una vez más la limitación de la herencia única de Java.
Características de acceso:
- La clase interna puede acceder directamente a los miembros de la clase externa, incluidos los miembros privados.
- Para que la clase externa acceda a los miembros de la clase interna, debe crear un objeto de la clase interna.
Clasificación y características comunes de las clases internas:
Características comunes:
- La clase interna sigue siendo una clase independiente; después de la compilación, se compila en un archivo `.class` independiente, pero se le antepone el nombre de la clase externa y el símbolo `$`.
- Las clases internas no se pueden acceder de la forma normal. Una clase interna es un miembro de la clase externa, por lo que puede acceder libremente a las variables miembro de la clase externa, ya sean o no `private`.
Clase interna miembro
En la clase externa hay variables miembro y métodos miembro; una clase interna miembro toma una clase completa como miembro de la clase externa.
La clase interna miembro se definedentro de la clase, fuera de los métodoscomo clase;
El formato para crear un objeto es:`NombreClaseExterna.NombreClaseInterna nombreObjeto = objetoClaseExterna.objetoClaseInterna`;
La razón por la que la clase interna miembro puede acceder directamente a los miembros de la clase externa es que la clase interna contiene una referencia al objeto de la clase externa:`NombreClaseExterna.this`;
Los modificadores que pueden usarse en una clase interna miembro son `final`, `abstract`, `public`, `private`, `protected`, `static`.
Clase interna estática
Una clase interna estática es una clase interna miembro con el modificador estático `static`, definidadentro de la clase, fuera de los métodos。
Hay dos escenarios para acceder a la clase interna estática desde la clase externa:
- Acceso desde la clase externa a los miembros no estáticos de la clase interna estática:*`NombreClaseExterna.NombreClaseInterna nombreObjeto = NombreClaseExterna.objeto``interno`*; se necesita acceder mediante la creación de un objeto;
- Acceso desde la clase externa a los miembros estáticos de la clase interna estática: también se puede usar el formato anterior, o usar directamente`NombreClaseExterna.NombreClaseInterna.miembro`。
Clase interna local
Una clase interna local es una clase definida dentro de un método.
- La clase interna de método solo puededentro del método que define la clase internaser instanciada; no se puede instanciar fuera de dicho método.
- Los objetos de la clase interna de método no pueden usar las variables locales no `final` del método donde se encuentra dicha clase interna.
Los modificadores que se pueden usar en la clase interna de método sonfinal,abstract;
La clase interna de método dentro de un método estático solo puede acceder amiembros estáticos externos。
Clase interna anónima
La clase interna anónima es una forma simplificada de clase interna; consiste en crear un objeto anónimo de una subclase de una clase externa o interfaz con contenido.
Requisito previo:
La clase interna puede heredar una clase externa o implementar una interfaz.
Formato:
`new NombreClaseExternaONombreInterfaz() { métodos sobrescritos };`
Normalmente, cuando el parámetro formal de un método es una interfaz o una clase abstracta, y los métodos de dicha interfaz no son más de tres, se puede pasar la clase interna anónima como argumento.
Contenido modificado por diferentes modificadores (no relacionado con clases internas)
| Clase | Variables miembro | Métodos miembro | Constructores | |
|---|---|---|---|---|
| private | Y | Y | Y | |
| Por defecto | Y | Y | Y | Y |
| protected | Y | Y | Y | |
| public | Y | Y | Y | Y |
| abstract | Y | Y | ||
| static | Y | Y | Y | |
| final | Y | Y | Y |
Atención, las reglas comunes son las siguientes:
- De ahora en adelante, todas las clases se modifican con `public`. Además, en un archivo Java solo se escribe una clase.
- De ahora en adelante, todas las variables miembro se modifican con `private`.
- De ahora en adelante, todos los métodos miembro se modifican con `public`.
Si es una clase abstracta o interfaz: `public abstract` + … - En adelante, todos los constructores deben modificarse con public.
Si la clase es una clase de utilidades o una clase singleton: el constructor se modifica con private.
Cuatro modificadores de acceso
| Misma clase | Mismo paquete (clases no relacionadas o subclases) | Diferente paquete (subclase) | Diferente paquete (clases no relacionadas) | |
|---|---|---|---|---|
| private | Y | |||
| Por defecto | Y | Y | ||
| protected | Y | Y | Y | |
| public | Y | Y | Y | Y |
Recomendación:
- Variables miembro: private
- Constructores: public
- Métodos miembro: public
Más tutoriales
Para tutoriales más detallados, consulte:Tutorial de Java
Fuente: http://www.codeceo.com/article/java-extends.html