Les sous-classes héritent-elles des champs privés?

Ceci est une question d’entrevue.

Les sous-classes héritent-elles des champs privés?

J’ai répondu “non”, car nous ne pouvons pas y accéder en utilisant “la méthode OOP normale”. Mais l’interviewer pense qu’ils sont hérités, car nous pouvons accéder à ces champs indirectement ou en utilisant la reflection et ils existent toujours dans l’object.

Après mon retour, j’ai trouvé la citation suivante dans le javadoc :

Membres privés dans une super classe

Une sous-classe n’hérite pas des membres privés de sa classe parente.

Connaissez-vous des arguments pour l’opinion de l’interviewer?

La plus grande partie de la confusion dans la question / les réponses entoure la définition de l’inheritance.

Evidemment, comme @DigitalRoss explique, un OBJET d’une sous-classe doit contenir les champs privés de sa super-classe. Comme il le dit, ne pas avoir access à un membre privé ne veut pas dire qu’il n’est pas là.

Toutefois. Ceci est différent de la notion d’inheritance pour une classe. Comme c’est le cas dans le monde java, où il y a une question de sémantique, l’arbitre est la spécification de langage Java (3ème édition actuelle).

Comme l’indique JLS ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 ):

Les membres d’une classe déclarée privée ne sont pas hérités par les sous-classes de cette classe. Seuls les membres d’une classe déclarée protégée ou publique sont hérités par des sous-classes déclarées dans un package autre que celui dans lequel la classe est déclarée.

Cela répond à la question exacte posée par l’enquêteur: “faire des sous- classes héritent des champs privés”. (emphase ajouté par moi)

La réponse est non. Ils ne le font pas. Les OBJETS des sous-classes contiennent des champs privés de leurs super-classes. La sous-classe elle-même n’a aucune NOTION de champs privés de sa super-classe.

Est-ce une sémantique de nature pédante? Oui. Est-ce une question d’interview utile? Probablement pas. Mais le JLS établit la définition du monde Java, et il le fait sans ambiguïté.

EDITED (a supprimé une citation parallèle de Bjarne Stroustrup qui, à cause des différences entre java et c ++, ne fait qu’append à la confusion. Je laisserai ma réponse sur le JLS 🙂

Oui

Il est important de réaliser que, même s’il y a deux classes, il n’y a qu’un seul object.

Donc, oui, bien sûr, il a hérité des champs privés. Ils sont vraisemblablement essentiels à la fonctionnalité des objects et, bien qu’un object de la classe parente ne soit pas un object de la classe dérivée, une instance de la classe dérivée est essentiellement une instance de la classe parente. Cela ne pourrait pas être très bien sans tous les champs.

Non, vous ne pouvez pas y accéder directement. Oui, ils sont hérités. Ils doivent être.

C’est une bonne question!


Mettre à jour:

Err, “non”

Eh bien, je suppose que nous avons tous appris quelque chose. Puisque le JLS est à l’origine du libellé exact “non hérité”, il est correct de répondre “non” . Comme la sous-classe ne peut pas accéder ou modifier les champs privés, en d’autres termes, ils ne sont pas hérités. Mais il n’y a vraiment qu’un seul object, il contient vraiment les champs privés, et si quelqu’un prend le langage JLS et le didacticiel dans le mauvais sens, il sera très difficile de comprendre la POO, les objects Java et ce qui se passe réellement.

Mise à jour pour mettre à jour:

La controverse comporte ici une ambiguïté fondamentale: que discute-t-on exactement? L’ object? Ou parlons-nous en quelque sorte de la classe elle-même? Beaucoup de latitude est autorisée pour décrire la classe par opposition à l’object. La sous-classe n’hérite donc pas des champs privés, mais un object qui est une instance de la sous-classe contient certainement les champs privés.

Les champs privés ne sont pas hérités … et c’est pourquoi Protected a été inventé. C’est par conception. Je suppose que cela justifiait l’existence d’un modificateur protégé.


Passons maintenant aux contextes. Qu’est-ce que vous entendez par hérité – s’il existe dans l’object créé à partir d’une classe dérivée? Oui, ça l’est.

Si vous voulez dire, peut-il être utile pour la classe dérivée. Et bien non.

Maintenant, quand vous arrivez à la functional programming, le champ privé de la super classe n’est pas hérité de manière significative pour la sous-classe . Pour la sous-classe, un champ privé de super classe est identique à un champ privé de toute autre classe.

Fonctionnellement, ce n’est pas hérité. Mais idéalement , c’est le cas.


OK, il suffit de regarder dans le tutoriel Java, ils citent ceci:

Membres privés dans une super classe

Une sous-classe n’hérite pas des membres privés de sa classe parente. Toutefois, si la super-classe a des méthodes publiques ou protégées pour accéder à ses champs privés, ceux-ci peuvent également être utilisés par la sous-classe.

référez-vous à: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

Je suis d’accord, que le champ est là. Mais la sous-classe ne bénéficie d’aucun privilège sur ce champ privé. Pour une sous-classe, le champ privé est identique à tout champ privé de toute autre classe.

Je crois que c’est uniquement une question de sharepoint vue. Vous pouvez modeler l’argument de chaque côté. C’est mieux justifier les deux manières.

Cela dépend de votre définition de “hériter”. La sous-classe a-t-elle toujours les champs en mémoire? Absolument. Peut-il y accéder directement? Non, ce ne sont que des subtilités de la définition; le but est de comprendre ce qui se passe réellement.

Je vais démontrer le concept avec le code. Les sous-classes héritent réellement des variables privées de super classe. Le seul problème est qu’ils ne sont pas accessibles aux objects enfants à moins que vous ne fournissiez des objects et des règles publics pour les variables privées dans la super classe.

Considérons deux classes dans le package Dump. L’enfant prolonge Parent.

Si je me souviens bien, un object enfant en mémoire se compose de deux régions. L’un est la partie parente seulement et l’autre est la partie enfant seulement. Un enfant peut accéder à la section privée du code de son parent uniquement via une méthode publique dans le parent.

Pense-y de cette façon. Le père de Borat, Boltok, possède un coffre-fort contenant 100 000 $. Il ne veut pas partager sa variable “privée” de sécurité. Donc, il ne fournit pas de clé pour le coffre-fort. Borat hérite du coffre-fort. Mais à quoi cela sert-il s’il ne peut même pas l’ouvrir? Si seulement son père avait fourni la clé.

Parent –

 package Dump; public class Parent { private Ssortingng reallyHidden; private Ssortingng notReallyHidden; public Ssortingng getNotReallyHidden() { return notReallyHidden; } public void setNotReallyHidden(Ssortingng notReallyHidden) { this.notReallyHidden = notReallyHidden; } }//Parent 

Enfant –

 package Dump; public class Child extends Parent { private Ssortingng childOnly; public Ssortingng getChildOnly() { return childOnly; } public void setChildOnly(Ssortingng childOnly) { this.childOnly = childOnly; } public static void main(Ssortingng [] args){ System.out.println("Testing..."); Child c1 = new Child(); c1.setChildOnly("childOnly"); c1.setNotReallyHidden("notReallyHidden"); //Attempting to access parent's reallyHidden c1.reallyHidden;//Does not even comstack }//main }//Child 

Non, ils n’en héritent pas.

Le fait qu’une autre classe puisse l’utiliser indirectement ne dit rien sur l’inheritance, mais sur l’encapsulation.

Par exemple:

 class Some { private int count; public void increment() { count++; } public Ssortingng toSsortingng() { return Integer.toSsortingng( count ); } } class UseIt { void useIt() { Some s = new Some(); s.increment(); s.increment(); s.increment(); int v = Integer.parseInt( s.toSsortingng() ); // hey, can you say you inherit it? } } 

Vous pouvez également obtenir la valeur de count dans UseIt via la reflection. Cela ne veut pas dire que vous en héritez.

METTRE À JOUR

Même si la valeur est là, elle n’est pas héritée par la sous-classe.

Par exemple une sous-classe définie comme:

 class SomeOther extends Some { private int count = 1000; @Override public void increment() { super.increment(); count *= 10000; } } class UseIt { public static void main( Ssortingng ... args ) { s = new SomeOther(); s.increment(); s.increment(); s.increment(); v = Integer.parseInt( s.toSsortingng() ); // what is the value of v? } } 

C’est exactement la même situation que dans le premier exemple. Le count atsortingbuts est masqué et pas du tout hérité par la sous-classe. Cependant, comme le souligne DigitalRoss, la valeur est là, mais pas par inheritance.

Mets le comme ça. Si votre père est riche et vous donne une carte de crédit, vous pouvez toujours acheter des choses avec son argent, mais cela ne signifie pas que vous avez hérité de tout cet argent, n’est-ce pas?

Autre mise à jour

Il est très intéressant de savoir pourquoi l’atsortingbut est là.

Je n’ai franchement pas le terme exact pour le décrire, mais c’est la machine virtuelle Java et son fonctionnement qui charge également la définition parente «non héritée».

Nous pourrions réellement changer le parent et la sous-classe fonctionnera toujours.

Par exemple :

 //A.java class A { private int i; public Ssortingng toSsortingng() { return ""+ i; } } // B.java class B extends A {} // Main.java class Main { public static void main( Ssortingng [] args ) { System.out.println( new B().toSsortingng() ); } } // Comstack all the files javac A.java B.java Main.java // Run Main java Main // Outout is 0 as expected as B is using the A 'toSsortingng' definition 0 // Change A.java class A { public Ssortingng toSsortingng() { return "Nothing here"; } } // Recomstack ONLY A.java javac A.java java Main // B wasn't modified and yet it shows a different behaviour, this is not due to // inheritance but the way Java loads the class Output: Nothing here 

Je suppose que le terme exact peut être trouvé ici: La spécification de la machine virtuelle JavaTM

Ok, c’est un problème très intéressant que j’ai beaucoup étudié et que j’ai conclu que les membres privés d’une super-classe sont effectivement disponibles (mais pas accessibles) dans les objects de la sous-classe. Pour le prouver, voici un exemple de code avec une classe parente et une classe enfant et j’écris un object de classe enfant dans un fichier txt et je lis un membre privé nommé «bhavesh» dans le fichier, prouvant ainsi qu’il est bien disponible chez l’enfant classe mais non accessible en raison du modificateur d’access.

 import java.io.Serializable; public class ParentClass implements Serializable { public ParentClass() { } public int a=32131,b,c; private int bhavesh=5555,rr,weq,refw; } 

 import java.io.*; import java.io.Serializable; public class ChildClass extends ParentClass{ public ChildClass() { super(); } public static void main(Ssortingng[] args) { ChildClass childObj = new ChildClass(); ObjectOutputStream oos; try { oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt")); oos.writeObject(childObj); //Writing child class object and not parent class object System.out.println("Writing complete !"); } catch (IOException e) { } } } 

Ouvrez MyData1.txt et recherchez le membre privé nommé ‘bhavesh’. S’il vous plaît laissez-moi savoir ce que vous en pensez.

Eh bien, ma réponse à la question de l’intervieweur est la suivante: les membres privés ne sont pas hérités dans des sous-classes, mais sont accessibles à l’object de sous-classe ou de sous-classe uniquement par des méthodes getter ou setter publiques ou par des méthodes appropriées de classe originale. La pratique normale est de garder les membres privés et d’y accéder en utilisant les méthodes getter et setter qui sont publiques. Alors, à quoi sert l’inheritance des méthodes getter et setter uniquement lorsque le membre privé avec lequel elles traitent n’est pas disponible pour l’object? Ici, «hérité» signifie simplement qu’il est disponible directement dans la sous-classe pour jouer avec les nouvelles méthodes introduites dans la sous-classe.

Enregistrez le fichier ci-dessous en tant que ParentClass.java et essayez-le vous-même ->

 public class ParentClass { private int x; public int getX() { return x; } public void setX(int x) { this.x = x; } } class SubClass extends ParentClass { private int y; public int getY() { return y; } public void setY(int y) { this.y = y; } public void setXofParent(int x) { setX(x); } } class Main { public static void main(Ssortingng[] args) { SubClass s = new SubClass(); s.setX(10); s.setY(12); System.out.println("X is :"+s.getX()); System.out.println("Y is :"+s.getY()); s.setXofParent(13); System.out.println("Now X is :"+s.getX()); } } Output: X is :10 Y is :12 Now X is :13 

Si nous essayons d’utiliser la variable privée x de ParentClass dans la méthode de SubClass, celle-ci n’est pas directement accessible pour les modifications (les moyens ne sont pas hérités). Mais x peut être modifié dans SubClass via la méthode setX () de la classe d’origine comme dans la méthode setXofParent () OU il peut être modifié à l’aide de l’object ChildClass en utilisant la méthode setX () ou la méthode setXofParent (). Donc, setX () et getX () sont des sortes de portes vers le membre privé x de ParentClass.

Un autre exemple simple est que la superclasse d’horloge a des heures et des minutes en tant que membres privés et des méthodes appropriées de lecture et de définition en tant que public. Puis vient DigitalClock en tant que sous-classe de Clock. Ici, si l’object DigitalClock ne contient pas d’heures et de minutes, les choses sont foutues.

Il semblerait qu’une sous-classe hérite des champs privés dans la mesure où ces champs sont utilisés dans le fonctionnement interne de la sous-classe (sur le plan philosophique). Une sous-classe, dans son constructeur, appelle le constructeur de la superclasse. Les champs privés de la superclasse sont évidemment hérités par la sous-classe appelant le constructeur de la superclasse si le constructeur de la superclasse a initialisé ces champs dans son constructeur. C’est juste un exemple. Mais bien sûr, sans méthodes d’access, la sous-classe ne peut pas accéder aux champs privés de la superclasse (c’est comme ne pas pouvoir faire apparaître le panneau arrière d’un iPhone pour réinitialiser le téléphone … mais la batterie est toujours là).

PS L’une des nombreuses définitions de l’inheritance que j’ai rencontrées: “Héritage – une technique de programmation qui permet à une classe dérivée d’étendre les fonctionnalités d’une classe de base, héritant de tous ses STATE (le mien est le mien) et de son comportement.”

Les champs privés, même s’ils ne sont pas accessibles par la sous-classe, constituent l’état hérité de la superclasse.

Disposition de la mémoire en Java face à l'héritage

entrer la description de l'image ici

Les bits de remplissage / alignement et l’inclusion de la classe d’objects dans le VTABLE ne sont pas pris en compte. L’object de la sous-classe a donc sa place pour les membres privés de la classe Super. Cependant, il n’est pas accessible à partir des objects de la sous-classe …

Je crois que la réponse dépend totalement de la question qui a été posée. Je veux dire, si la question est

Pouvons-nous accéder directement au domaine privé de la super-classe de leur sous-classe?

Alors, la réponse est non . Si nous passons en revue les détails du spécificateur d’access , cela est mentionné, les membres privés ne sont accessibles que dans la classe elle-même.

Mais si la question est

Pouvons-nous accéder au domaine privé de la super-classe de leur sous-classe?

Ce qui signifie que ce n’est pas grave ce que vous allez faire pour accéder au membre privé. Dans ce cas, nous pouvons rendre la méthode publique dans la super-classe et accéder au membre privé. Donc, dans ce cas, vous créez une interface / pont pour accéder au membre privé.

D’autres langages tels que C ++, ont le concept de friend function , par lequel nous pouvons accéder au membre privé d’une autre classe.

Je pense que le champ privé n’est pas hérité, car la sous-classe ne peut pas y accéder directement. ou en d’autres termes, je pense que la méthode (y compris l’access au champ privé) a hérité mais pas le champ.

Nous pouvons simplement affirmer que lorsqu’une super-classe est héritée, alors les membres privés de la super-classe deviennent en réalité des membres privés de la sous-classe et ne peuvent plus être hérités ou sont inaccessibles aux objects de la sous-classe.

Je devrais répondre que les champs privés en Java sont hérités. Permettez-moi de démontrer:

 public class Foo { private int x; // This is the private field. public Foo() { x = 0; // Sets int x to 0. } //The following methods are declared "final" so that they can't be overridden. public final void update() { x++; } // Increments x by 1. public final int getX() { return x; } // Returns the x value. } public class Bar extends Foo { public Bar() { super(); // Because this extends a class with a constructor, it is required to run before anything else. update(); //Runs the inherited update() method twice update(); System.out.println(getX()); // Prints the inherited "x" int. } } 

Si vous exécutez un programme Bar bar = new Bar(); , alors vous verrez toujours le numéro “2” dans la boîte de sortie. Comme l’entier “x” est encapsulé avec les méthodes update() et getX() , il peut être prouvé que l’entier est hérité.

La confusion est que parce que vous ne pouvez pas accéder directement à l’entier “x”, alors les gens affirment qu’il n’est pas hérité. Cependant, chaque chose non statique dans une classe, que ce soit le champ ou la méthode, est héritée.

Un membre de classe privé ou un constructeur est accessible uniquement dans le corps de la classe de niveau supérieur ( §7.6 ) qui contient la déclaration du membre ou du constructeur. Il n’est pas hérité par les sous-classes. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

Une sous-classe n’hérite pas des membres privés de sa classe parente. Toutefois, si la super-classe a des méthodes publiques ou protégées pour accéder à ses champs privés, ceux-ci peuvent également être utilisés par la sous-classe.

Les membres privés (état et comportement) sont hérités. Ils (peuvent) affecter le comportement et la taille de l’object instancié par la classe. Sans compter qu’ils sont très bien visibles par les sous-classes via tous les mécanismes de coupure d’encapsulation disponibles ou pouvant être assumés par leurs implémenteurs.

Bien que l’inheritance ait une définition “de facto”, il n’a absolument aucun lien avec les aspects de “visibilité”, qui sont assumés par les réponses “non”.

Donc, il n’y a pas besoin d’être diplomatique. JLS a tout simplement tort à ce stade.

Toute hypothèse selon laquelle ils ne sont pas “hérités” est dangereuse et dangereuse.

Ainsi, parmi deux définitions de facto (partiellement) contradictoires (que je ne répéterai pas), la seule qui devrait être suivie est celle qui est la plus sûre (ou la plus sûre).