Animal(animal):
public class Animal {
String name;
int age;
} Podemos crear para ello, por ejemplo, 2 clases descendientes: Caty Dog. Esto se hace usando la palabra clave extends.
public class Cat extends Animal {
}
public class Dog extends Animal {
} Esto puede resultarnos útil en el futuro. Por ejemplo, si la tarea es cazar ratones, crearemos un objeto en el programa Cat. Si la tarea es correr detrás de un palo, entonces usamos el objeto Dog. Y si creamos un programa que simule una clínica veterinaria, funcionará con la clase Animal(para poder tratar tanto a perros como a gatos). Es muy importante recordar para el futuro que al crear un objeto, primero se llama al constructor de su clase base , y solo entonces se llama al constructor de la clase en sí, cuyo objeto estamos creando. Es decir, al crear un objeto, Catprimero funcionará el constructor de la clase Animal, y solo después el constructor Cat. Para asegurarnos de esto, agreguemos a los constructores Caty Animalenviemos a la consola.
public class Animal {
public Animal() {
System.out.println("Constructor de animales completado");
}
}
public class Cat extends Animal {
public Cat() {
System.out.println("¡El constructor Cat funcionó!");
}
public static void main(String[] args) {
Cat cat = new Cat();
}
} Salida de consola:
Отработал конструктор Animal
Отработал конструктор Cat! De hecho, ¡así es como funciona todo! ¿Para qué sirve? Por ejemplo, para evitar duplicar campos comunes de dos clases. Por ejemplo, todo animal tiene corazón y cerebro, pero no todos los animales tienen cola. Podemos declarar campos comunes a todos los animales brainen heartla clase principal Animaly un campo tailen la subclase Cat. Ahora crearemos un constructor para la clase Cat, donde pasaremos los 3 campos.
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
public static void main(String[] args) {
Cat cat = new Cat("Cerebro", "Corazón", "Cola");
}
}Prestar atención:El constructor funciona correctamente, aunque la clase Catno tiene campos brainy heart. Estos campos fueron "extraídos" de la clase base Animal. La clase descendiente tiene acceso a los campos de la clase base, por lo que Catson visibles en nuestra clase. Por lo tanto, no necesitamos Catduplicar estos campos en la clase; podemos tomarlos de la clase Animal. Además, podemos llamar explícitamente al constructor de la clase base en el constructor de la clase descendiente. La clase base también se llama " superclase ", razón por la cual Java usa la palabra clave super. En el ejemplo anterior
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
} Asignamos por separado cada campo que está en nuestra clase principal. De hecho, no es necesario que haga esto. Basta con llamar al constructor de la clase padre y pasarle los parámetros necesarios:
public class Animal {
String brain;
String heart;
public Animal(String brain, String heart) {
this.brain = brain;
this.heart = heart;
}
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
this.tail = tail;
}
public static void main(String[] args) {
Cat cat = new Cat("Cerebro", "Corazón", "Cola");
}
} En el constructor, Catllamamos al constructor Animaly le pasamos dos campos. Sólo tenemos que inicializar explícitamente un campo, tailque Animalno está presente. ¿Recuerda que dijimos que cuando se crea un objeto, primero se llama al constructor de la clase principal? ¡Es por eso que la palabra super()siempre debe aparecer primero en el constructor! De lo contrario, la lógica de los constructores se romperá y el programa generará un error.
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
this.tail = tail;
super(brain, heart);//¡error!
}
public static void main(String[] args) {
Cat cat = new Cat("Cerebro", "Corazón", "Cola");
}
} El compilador sabe que al crear un objeto de una clase descendiente, se llama primero al constructor de la clase base. Y si intenta cambiar manualmente este comportamiento, no lo permitirá.
El proceso de creación de un objeto.
Arriba vimos un ejemplo con una clase base y principal:Animaly Cat. Ahora, usando estas dos clases como ejemplo, veremos el proceso de creación de un objeto e inicialización de variables. Sabemos que las variables son estáticas y variables de instancia (no estáticas). También sabemos que la clase base Animaltiene sus propias variables y la clase descendiente Cattiene las suyas propias. Agreguemos una variable estática a la clase para Animalmayor claridad . CatLa variable animalCountde clase Animalsería el número total de especies animales en la Tierra y la variable catsCountsería el número de especies de gatos. Además, asignaremos valores iniciales a todas las variables no estáticas de ambas clases (que luego cambiarán en el constructor).
public class Animal {
String brain = "El valor inicial del cerebro en la clase Animal";
String heart = "El valor inicial de corazón en la clase Animal";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("Se está ejecutando el constructor de la clase base Animal");
System.out.println("¿Ya se inicializaron las variables de la clase Animal?");
System.out.println("El valor actual de la variable estática animalCount = " + animalCount);
System.out.println("Valor actual del cerebro en la clase Animal =" + this.brain);
System.out.println("Valor actual del corazón en la clase Animal =" + this.heart);
System.out.println("¿Ya se inicializaron las variables de la clase Cat?");
System.out.println("El valor actual de la variable estática catsCount = " + Cat.catsCount);
this.brain = brain;
this.heart = heart;
System.out.println("¡Constructor de clase base animal completado!");
System.out.println("Valor actual del cerebro =" + this.brain);
System.out.println("Valor actual del corazón = " + this.heart);
}
}
public class Cat extends Animal {
String tail = "El valor inicial de la cola en la clase Cat";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("Se ha iniciado el constructor de la clase Gato (ya se ha ejecutado el constructor Animal)");
System.out.println("El valor actual de la variable estática catsCount = " + catsCount);
System.out.println("Valor actual cola =" + this.tail);
this.tail = tail;
System.out.println("Valor actual cola =" + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Cerebro", "Corazón", "Cola");
}
} Entonces, creamos un nuevo objeto de la clase Catheredada de Animal. Agreguemos una salida de consola detallada a nuestro programa para ver qué sucederá y en qué orden. Esto es lo que se mostrará en la consola como resultado de la creación de un objeto Cat:
Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее significado статической переменной animalCount = 7700000
Текущее significado brain в классе Animal = Изначальное significado brain в классе Animal
Текущее significado heart в классе Animal = Изначальное significado heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее significado статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее significado brain = Мозг
Текущее significado heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее significado статической переменной catsCount = 37
Текущее significado tail = Изначальное significado tail в классе Cat
Текущее significado tail = Хвост Entonces, ahora podemos ver claramente en qué orden se inicializan las variables y se llaman los constructores al crear un nuevo objeto:
-
Se inicializan las variables estáticas de la clase base ( )
Animal. En nuestro caso, a la variableanimalCountde claseAnimalse le asigna el valor 7700000. -
Se inicializan las variables estáticas de la clase descendiente ( )
Cat. Preste atención: todavía estamos dentro del constructorAnimaly la consola ya dice:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее significado статической переменной animalCount = 7700000 Текущее significado brain в классе Animal = Изначальное significado brain в классе Animal Текущее significado heart в классе Animal = Изначальное significado heart в классе Animal Были ли уже проинициализированы переменные класса Cat? Текущее significado статической переменной catsCount = 37 -
A continuación, se inicializan las variables no estáticas de la clase base . Les asignamos específicamente valores iniciales, que luego se cambian por otros nuevos en el constructor. El constructor
Animalaún no ha completado su trabajo, pero ya sebrainhanheartasignado los valores iniciales:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее significado статической переменной animalCount = 7700000 Текущее significado brain в классе Animal = Изначальное significado brain в классе Animal Текущее significado heart в классе Animal = Изначальное significado heart в классе Animal -
El constructor de la clase base comienza a funcionar .
Ya hemos visto que esta etapa es solo la cuarta consecutiva: en los primeros tres puntos, en el momento en que el constructor comienza a trabajar,
Animalya se han asignado valores a muchas variables. -
Inicializando campos no estáticos de una clase secundaria (
Cat).Sucede antes de que el diseñador
Catcomience a trabajar.En el momento en que empezó a trabajar, la variable
tailya tenía un valor:Конструктор класса Cat начал работу (конструктор Animal уже был выполнен) Текущее significado статической переменной catsCount = 37 Текущее significado tail = Изначальное significado tail в классе Cat -
El constructor de la clase descendiente se llama
Cat
GO TO FULL VERSION