Pourquoi le constructeur de super classe est-il invoqué lorsque nous déclarons l'objet de la sous-classe? (Java)
Considérez ce code:
class Test {
Test() {
System.out.println("In constructor of Superclass");
}
int adds(int n1, int n2) {
return(n1+n2);
}
void print(int sum) {
System.out.println("the sums are " + sum);
}
}
class Test1 extends Test {
Test1(int n1, int n2) {
System.out.println("In constructor of Subclass");
int sum = this.adds(n1,n2);
this.print(sum);
}
public static void main(String[] args) {
Test1 a=new Test1(13,12);
Test c=new Test1(15,14);
}
}
Si nous avons un constructeur en super classe, il sera invoqué par chaque objet que nous construire pour la classe enfant (ex. L'objet ' a ' pour la classe test1 appelle Test1 (int n1, int n2) ainsi que Test ()).
Pourquoi cela arrive-t-il?
La sortie de ce programme est:
Dans le constructeur de superclasse
Dans le constructeur de la sous-classe
Les sommes sont 25
Dans le constructeur de superclasse
Dans constructeur de la sous-classe
Les sommes sont 29
18 réponses
Car il s'assurera que lorsqu'un constructeur est appelé, il peut compter sur tous les champs de sa superclasse en cours d'initialisation.
Voir 3.4.4 dans ici
Oui. Une superclasse doit être construite avant qu'une classe dérivée puisse également être construite, sinon certains champs qui devraient être disponibles dans la classe dérivée pourraient ne pas être initialisés.
Une petite note: si vous devez appeler explicitement le constructeur de super classe pour lui transmettre certains paramètres:
baseClassConstructor(){
super(someParams);
}
Alors le super constructeur doit être le premier appel de méthode dans le constructeur dérivé. Par exemple, cela ne compile pas:
baseClassConstructor(){
foo();
super(someParams); // compilation error
}
Super () est ajouté automatiquement dans chaque constructeur de classe par le compilateur.
Comme nous le savons bien, le constructeur par défaut est fourni automatiquement par le compilateur, mais il ajoute également super() pour la première instruction.Si vous créez votre propre constructeur et que vous n'avez ni this () ni super () comme première instruction, le compilateur fournira super () comme première instruction du constructeur.
Les classes Java sont instanciées dans l'ordre suivant:
(au moment du chargement de classe) 0. initialiseurs pour les membres statiques et les blocs d'initialisation statiques, dans l'ordre de la déclaration.
(à chaque nouvel objet)
- créer des variables locales pour les arguments du constructeur
- si le constructeur commence par l'appel d'un autre constructeur pour classe, évaluer les arguments et revenir à l'étape précédente. Toutes les étapes sont complétés pour ce constructeur, y compris d'autres la récursivité de constructeur appelle, avant de continuer.
- Si la superclasse n'a pas été construite par ce qui précède, construisez le la superclasse (en utilisant le constructeur no-arg s'il n'est pas spécifié). Comme #2, passez par toutes ces étapes pour la superclasse, y compris la construction C'est superclasse, avant de continuer.
- initialiseurs par exemple variables et blocs d'initialisation non statiques, dans l'ordre de déclaration.
- reste du constructeur.
La sous-classe hérite des champs de sa(ses) superclasse (s) et ces champs ont pour être construits/initialisés (c'est le but habituel d'un constructeur: initialiser les membres de la classe afin que l'instance fonctionne comme requis. Nous savons que certaines personnes mais beaucoup plus de fonctionnalités dans ces pauvres constructeurs...)
Constructeur implémente la logique qui rend l'objet prêt à fonctionner. L'objet peut contenir l'état dans les champs privés, de sorte que seules les méthodes de sa classe peuvent y accéder. Donc, si vous souhaitez que l'instance de votre sous-classe soit vraiment prête à fonctionner après avoir appelé le constructeur (c'est-à-dire que toutes ses fonctionnalités, y compris héritées de la classe de base, sont correctes), le constructeur de la classe de base doit être appelé.
C'est pourquoi le système fonctionne de cette façon.
Automatiquement le constructeur par défaut de la classe de base est appelé. Si vous vous voulez changer cela, vous devez appeler explicitement le constructeur de la classe de base en écrivant super()
dans la première ligne du constructeur de votre sous-classe.
Le constructeur de classe de base sera appelé avant le constructeur de classe dérivé. Cela a du sens car cela garantit que la classe de base est correctement construite lorsque le constructeur de la classe dérivée est exécuté. Cela vous permet d'utiliser certaines des données à partir de la classe de base lors de la construction de la classe dérivée.
Lorsque nous créons un objet de sous-classe, il doit prendre en considération toutes les fonctions membres et les variables membres définies dans la superclasse. Un cas peut survenir dans lequel une variable membre peut être initialisée dans certains constructeurs de superclasse. par conséquent, lorsque nous créons un objet sous-classe, tous les constructeurs de l'arbre d'héritage correspondant sont appelés de la manière Haut-Bas.
Plus précisément lorsqu'une variable est définie comme protégée elle sera toujours accessible dans la sous-classe que la sous-classe se trouve ou non dans le même paquet. Maintenant, à partir de la sous-classe si nous appelons une fonction de superclasse pour imprimer la valeur de cette variable protégée(qui peut être initialisée dans le constructeur de la superclasse), nous devons obtenir la valeur initialisée correcte.Par conséquent, tous les constructeurs de superclasse sont invoqués.
En interne Java appelle super () dans chaque constructeur. Donc chaque constructeur de sous classe appelle son constructeur de superclasse en utilisant super () et donc ils sont exécutés de haut en bas.
Note: les fonctions peuvent être remplacées pas les variables.
Puisque vous héritez des propriétés de la classe de base dans la classe dérivée, il peut y avoir des situations où votre constructeur de classe dérivée nécessite certaines des variables de la classe de base pour initialiser ses variables. Donc, il doit d'abord initialiser les variables de classe de base, puis les variables de classe dérivées. C'est pourquoi Java appelle le premier constructeur de classe de base, puis le constructeur de classe dérivé.
Et aussi il ne fait aucun sens pour initialiser la classe enfant sans initialiser la classe parent.
Constructeur de Super class In appelé en premier parce que toutes les méthodes du programme sont d'abord présentes dans le tas et après la compilation, elles sont stockées dans la pile, en raison de laquelle le constructeur de super class est appelé en premier.
En termes simples si super class A paramétré le constructeur, vous devez appeler explicitement super (params)dans la première ligne de votre constructeur de classe enfant sinon implicitement tous les constructeurs de super class sont appelés jusqu'à ce que la classe object soit atteinte.
Il y a un appel par défaut super () dans vos constructeurs par défaut de sous-classes.
//Default constructor of subClass
subClass() {
super();
}
" si un constructeur n'invoque pas explicitement un constructeur de superclasse, le compilateur Java insère automatiquement un appel au constructeur sans argument de la superclasse. Si la super-classe ne possède pas de constructeur sans argument, vous obtiendrez une erreur de compilation. Object a un tel constructeur, donc si Object est la seule superclasse, il n'y a pas de problème."
(source: https://docs.oracle.com/javase/tutorial/java/IandI/super.html )
Je vais essayer de répondre à cela d'un point de vue différent.
Supposons que Java n'ait pas appelé automatiquement le super constructeur pour vous. Si vous héritez de la classe, vous devrez soit appeler implicitement le super constructeur, soit le réécrire vous-même. Cela vous obligerait à avoir une connaissance interne du fonctionnement de la super classe, ce qui est mauvais. Il faudrait également réécrire le code, ce qui n'est pas bon non plus.
Je suis d'accord que l'appel du Super constructeur dans les coulisses est un peu à peu intuitive. D'un autre côté, Je ne sais pas comment ils auraient pu le faire d'une manière plus intuitive.
Comme nous le savons, les variables membres (champs)d'une classe doivent être initialisées avant de créer un objet car ces champs représentent l'état de l'objet. Si ces champs ne sont pas explicitement initialisés, le compilateur leur fournit implicitement des valeurs par défaut en appelant le constructeur par défaut sans argument. C'est pourquoi le constructeur de sous-classe appelle le constructeur par défaut super class no-argument ou implicitement invoqué par le compilateur .Les variables locales ne sont pas fournies par défaut par le compilateur.
Ici, votre Test d'extension à votre classe test1 signifie que vous pouvez accéder à toutes les méthodes et variables de test dans votre test1. gardez à noter que vous ne pouvez accéder à une méthode de classe ou à une variable que si de la mémoire lui est allouée et pour cela il a besoin d'un constructeur par défaut ou paramétré, donc ici le compilateur trouve qu'il étend une classe il essaiera de trouver le constructeur de super classe afin que vous puissiez accéder à toutes
Les Parents Sortent D'Abord!! Et comme L'enfant du monde réel ne peut pas exister sans les Parents.. L'initialisation des parents (superclasse) est donc importante pour utiliser thrm dans les Classes children(sous-classe)..