simple - Herencia en Java: la creación de un objeto de la subclase invoca también el constructor de la superclase. ¿Por qué exactamente?
polimorfismo java (15)
Tengo una pregunta sobre la herencia en Java.
Tengo dos clases A
y B
, y clase B, hereda de A:
public class A {
public A() {
System.out.println("Hi!");
}
}
public class B extends A {
public B() {
System.out.println("Bye!");
}
public static void main(String[] args) {
B b = new B();
}
}
Cuando ejecuto el programa B, el resultado es:
Hi!
Bye!
Pregunta : ¿por qué se invoca el constructor de la
class A
, cuando creo y me opongo a laclass B
?
Sé que B hereda todo de A - todas las variables de instancia o clase, y todos los métodos, y en este sentido un objeto de B tiene todas las características de A más algunas otras características definidas en B. Sin embargo, no sabía y no lo hice Imagino que cuando creo un objeto de tipo B, también se invoca el constructor de A. Entonces, escribiendo esto:
B b = new B();
crea dos objetos: uno de tipo B y uno de tipo A.
Esto se está poniendo interesante,
¿Alguien puede explicar por qué exactamente sucede esto?
Cada superclase tiene un constructor y cada constructor de la jerarquía se ejecuta en el momento en que se crea un objeto de una subclase.
Cuando se crea un objeto de clase secundaria, internamente no se creó para el objeto de clase superior. Pero la memoria debe asignarse a los miembros de la clase superior.
Cuando se crea un objeto nuevo (B), se crea dentro del objeto BA (debido a que se amplían las palabras clave). En la clase B, JVM busca el constructor de la clase B, pero debido a las palabras clave extendidas va al constructor de la clase superior. inside Se inicializa un valor de clase x. Pero x es privado, de modo que podemos acceder al método getXxx()
tiro fuera de clase y obtener el resultado.
El constructor contiene toda la inicialización para A. No está creando dos objetos. Está creando un objeto, luego ejecuta el inicializador para la superclase para inicializar sus miembros y luego ejecuta el inicializador para la clase derivada para inicializar sus miembros.
El constructor de una clase es un concepto muy importante en la mayoría de los OOP
Las clases, al proporcionar el estado y los medios para manipular ese estado, permiten el mantenimiento más fácil de las invariantes. El rol de los constructores es llevar la clase a un estado que se ajuste a esas invariantes (o que impida el uso de un objeto inviable). esto es algo más flexible de lo que se pretendía en muchos lenguajes, ya que el constructor puede pasar su propia referencia "this" en otro lugar, pero al menos está bajo el control de la clase (como tal, puede saber que está en un estado suficientemente estable y válido) para que sea accesible al resto del mundo)
La herencia lo hace complejo ya que B es-a A en un sentido muy real y por lo tanto puede invocar cualquiera de los métodos proporcionados por A. Las partes de B que son A deberían tener la oportunidad de inicializarse antes de que B eche un vistazo, por lo tanto se llama al constructor de A antes de que comience el trabajo real del constructor B.
En java cuando creas un objeto de clase hija, el constructor de la clase padre siempre se llama porque la clase Object es la principal de cada superclase y cuando llamas al constructor de la clase Object, solo tu objeto es creado y java no admite herencia múltiple en caso de clase, entonces si extiende cualquier otra clase, entonces la relación entre su clase hija y la clase Object es a través de la clase Parent, por lo que para llamar al constructor de la clase Object debe llamarse al constructor de la clase Parent.
Esto se hace porque el constructor se usa para inicializar el objeto. Como B también es una A, llama primero al constructor para A, luego al constructor para B.
Como nota al margen, puede usar super(arg1, etc)
para elegir a qué constructor de A se llama en función de los tipos de parámetros que pasa ... pero debe ser la primera línea del constructor.
La creación de B no crea una A adicional.
Pero al crear B, creas un tipo de A, porque B es un A.
Java / C ++ llama implícitamente al constructor de A para usted. ¿Por qué? Diseño del lenguaje. Pero hacerlo está bien, porque el constructor de A podría contener algunas inicializaciones. Y como B usa todas las características y errores de A, estas características se inicializan mejor.
No crea 2 objetos, solo crea una instancia de B. La razón por la que se invoca el constructor de la superclase es porque, como dijiste, B tiene todos los campos de A, y estos campos deben inicializarse.
No crea dos objetos, solo crea un objeto b. b es de tipo B y de tipo A. Un constructor básicamente dice que esto es lo que tienes que hacer para construirme. Entonces, cuando está creando una nueva instancia "B", está construyendo un objeto que es tanto B () como A (). Imagine el siguiente escenario:
class Q {
int i;
public Q() {
// set default value
i= 99;
}
}
class Z extends Q {
public Z() {
}
}
Si el constructor para Q WAS NOT fue llamado, ¿cómo obtendría su valor predeterminado?
No crea dos objetos, solo uno: B.
Al heredar de otra clase, debes llamar a super () en tu constructor. Si no lo hace, el compilador insertará esa llamada como puede ver claramente.
Se llama a los constructores de superclase porque, de lo contrario, el objeto se dejaría en un estado no inicializado, posiblemente sin que el desarrollador de la subclase lo supiera.
Su subclase en realidad se ve así después de que el compilador inserta la súper llamada:
public class B extends A {
public B() {
super();
System.out.println("Bye!");
}
}
Recuerde que la herencia es una relación "es una" entre la clase base y la subclase, por lo que cada vez que tenga una instancia de una subclase, por definición también tendrá una instancia de la clase base (como parte de la instancia, no como dos instancias separadas). Para inicializar correctamente la clase base, se llama al constructor.
Además, piense qué sucedería si la subclase dependiera de algún estado interno de la clase base. ¿No querrías entonces que la instancia de la clase base se inicializara?
Si A inicializa miembros en su constructor y se olvida de llamar a super en su clase derivada, entonces los miembros de A podrían estar en mal estado. Java está tratando de evitar que te pegues un tiro en el pie.
Solo se crea un objeto, ambos contratistas se ejecutan en el mismo objeto.
La razón es simple, ya que sabes que B tiene todas las variables y métodos de A, por lo que si alguna de las variables de A necesita inicializarse para que los métodos de A puedan funcionar, alguien tiene que inicializarlo y ese alguien es el constructor de A.
por ejemplo:
public class A {
public A() {
x = 1;
}
private int x;
public int getX() {
return x;
}
}
public class B extends A {
public B() {
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.getX()); // should print 1
}
}
si el objeto superclase no se crea, entonces la subclase accede a los métodos y variables no estáticos de la superclase.
Estudié que los métodos no estáticos y las variables solo se puede acceder a través de objetos ..