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

il s'agit d'une question d'entrevue.

Ne sous-classes héritent privé les champs?

j'ai répondu" non", parce que nous ne pouvons pas y accéder en utilisant la"voie normale OOP". Mais l'intervieweur pense qu'ils sont hérités, parce que nous pouvons accéder à de tels champs indirectement ou en utilisant la réflexion et ils existent toujours dans l'objet.

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

Membres Privés dans une super-classe

A sous-classe n'hérite pas de la privée les membres de sa classe parente.

avez-vous des arguments pour justifier l'opinion de l'intervieweur?

211
demandé sur Peter O. 2011-01-17 20:34:18

17 réponses

la plus grande partie de la confusion dans la question/réponse concerne la définition de L'héritage.

évidemment, comme @DigitalRoss explique un objet d'une sous-classe doit contenir les champs privés de sa superclasse. Comme il le dit, ne pas avoir accès à un membre privé ne signifie pas qu'il n'est pas là.

cependant. C'est différent de la notion d'héritage d'une classe. Comme c'est le cas dans le monde java, où il y a un question de sémantique l'arbitre est le Java Language Specification (actuellement 3e édition).

comme le dit le JLS ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 ):

membres d'une classe qui sont déclarés privés ne sont pas hérités par les sous-classes de cette classe. Uniquement les membres d'une classe déclarée protégée ou publiques sont héritées par les sous-classes déclaré dans un emballage autre que le celui dans lequel la classe est déclarée.

il s'agit de la question exacte posée par l'intervieweur: "do sub CLASSES hériter des champs privés". (c'est moi qui souligne)

la réponse est non. Ils ne le font pas. Les objets des sous-classes contiennent des champs privés de leurs superclasses. La sous-classe elle-même N'a aucune NOTION des champs privés de sa superclasse.

est-ce une sémantique de nature pédante? Oui. Est-ce une question d'entrevue utile? Probablement pas. Mais le JLS établit la définition du monde Java, et il le fait (dans ce cas-ci) sans ambiguïté.

ÉDITÉ (supprimé en parallèle une citation de Bjarne Stroustrup qui, en raison des différences entre java et c++ probablement qu'ajouter à la confusion. Je laisse ma réponse reposer sur le JLS :)

208
répondu robert_x44 2016-03-11 12:01:04

Oui

il est important de se rendre compte que s'il y a deux classes , il n'y a qu'un seul objet.

donc, oui, bien sûr, il a hérité des champs privés. Ils sont, vraisemblablement, essentiels pour une fonctionnalité correcte de l'objet, et bien qu'un objet de la classe mère ne soit pas un objet de la classe dérivée, une instance de la classe dérivée est certainement une instance de la classe mère. Il n'a pas pu être bien que sans tous les champs.

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

c'est une bonne question!


mise à jour:

Err","

Eh bien, je suppose que nous avons tous appris quelque chose. Depuis le JLS l'origine exacte "pas hérité" libellé, il est correct de répondre "non" . Puisque la sous-classe ne peut pas accéder ou modifier les champs privés, alors, en d'autres termes, ils ne sont pas hérités. Mais il y a vraiment est juste un objet, il vraiment ne contient les champs privés, et donc si quelqu'un prend le JLS et tutoriel libellé de la mauvaise façon, il sera très difficile de comprendre OOP, Java objets, et ce qui est vraiment happening.

mise à jour:

la controverse ici implique une ambiguïté fondamentale: que discute-t-on exactement? l'objet ? ou s'agit-il en quelque sorte de la classe elle-même? beaucoup de latitude est permise pour décrire la classe par opposition à l'objet. Ainsi, le sous-classe n'hérite pas privé champs, mais un objet qui est une instance de la sous-classe contient certainement les champs privés.

67
répondu DigitalRoss 2016-10-07 19:04:52

Pas de. Champs privés ne sont pas héritées... et c'est pourquoi protégé a été inventé. C'est par la conception. Je suppose que cela justifiait l'existence d'un modificateur protégé.


maintenant dans les contextes. Que voulez-vous dire par hérité -- si il est là dans l'objet créé à partir de la classe dérivée? oui, il est.

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

maintenant, quand vous venez à la programmation fonctionnelle le domaine privé de super classe n'est pas hérité d'une manière significative pour la sous-classe . Pour la sous-classe, un champ privé de la super-classe est la même qu'un champ privé de toute autre classe.

fonctionnellement, il n'est pas hérité. Mais idéalement , il est.


OK, juste regardé 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 d'origine. Toutefois, si la superclasse dispose de moyens publics ou protégés pour accéder à ses champs privés, ceux-ci peuvent également être utilisés par la sous-classe.

refer: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

je suis d'accord, que le champ est là. Mais, la sous-classe n'obtient aucun privilège sur ce domaine privé. Pour une sous-classe, le domaine privé est le même que dans tout domaine privé de toute autre classe.

je crois que c'est purement une question de point de vue. Vous pouvez modeler l'argument de chaque côté. Il est préférable de justifier à la fois.

18
répondu Nishant 2016-06-27 09:53:47

Cela dépend de votre définition de "hériter". La sous-classe A-t-elle encore les champs en mémoire? Certainement. Peut-il y accéder directement? Aucun. Ce ne sont que des subtilités de la définition; le but est de comprendre ce qui se passe réellement.

10
répondu Mehrdad 2011-01-17 17:36:21

je vais démontrer le concept avec du code. Sous-classes en fait hériter les variables privées de la super classe. Le seul problème est qu'ils ne sont pas accessible à la les objets enfant à moins que vous ne fournissiez des getters publics et des setters pour les variables privées dans la super-classe.

considérer deux classes dans le paquet Dump. Enfant étend Parent.

si je me souviens bien, un objet enfant dans la mémoire se compose de deux régions. L'un est la partie parent seulement et l'autre est la partie enfant seulement. Un enfant peut avoir accès au section dans le code de sa société mère seulement par une méthode publique dans la société mère.

pensez-y. Le père de Borat, Boltok, a un coffre contenant 100 000$. Il ne veut pas partager son "privé" variable. Donc, il ne fournit pas une clé pour le coffre. Borat hérite du coffre. Mais à quoi bon s'il ne peut même pas l'ouvrir ? Si seulement sa papa avait fourni la clé.

Parent -

package Dump;

public class Parent {

    private String reallyHidden;
    private String notReallyHidden;

    public String getNotReallyHidden() {
        return notReallyHidden;
    }

    public void setNotReallyHidden(String notReallyHidden) {
        this.notReallyHidden = notReallyHidden;
    }

}//Parent

enfant -

package Dump;

public class Child extends Parent {

    private String childOnly;

    public String getChildOnly() {
        return childOnly;
    }

    public void setChildOnly(String childOnly) {
        this.childOnly = childOnly;
    }

    public static void main(String [] 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 compile

    }//main

}//Child
9
répondu Borat Sagdiyev 2014-05-12 00:46:58

Pas de. Ils n'héritent pas.

le fait qu'une autre classe puisse l'utiliser indirectement ne dit rien au sujet de l'héritage, mais au sujet de l'encapsulation.

par exemple:

class Some { 
   private int count; 
   public void increment() { 
      count++;
   }
   public String toString() { 
       return Integer.toString( count );
   }
}

class UseIt { 
    void useIt() { 
        Some s = new Some();
        s.increment();
        s.increment();
        s.increment();
        int v = Integer.parseInt( s.toString() );
        // hey, can you say you inherit it?
     }
}

vous pouvez également obtenir la valeur de count à l'intérieur de UseIt par réflexion. Il n'a pas les moyens, vous en hériter.

mise à JOUR

, Même si la valeur est là, il 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( String ... args ) { 
        s = new SomeOther();
        s.increment();
        s.increment();
        s.increment();
        v = Integer.parseInt( s.toString() );
        // what is the value of v?           
     }
}

C'est exactement la même situation que le premier exemple. L'attribut count est caché et n'est pas du tout hérité de la sous-classe. Cependant, comme DigitalRoss le souligne, la valeur est là, mais pas par voie de succession.

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

autre mise à jour

il est très intéressant cependant, de savoir pourquoi l'attribut est là.

Je n'ai franchement pas le terme exact pour le décrire, mais c'est la JVM et la façon dont elle fonctionne qui charge aussi le " non hérité" définition du parent.

nous pourrions en fait changer le parent et la sous-classe fonctionnera toujours.

Par exemple :

//A.java
class A {
   private int i;
   public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
   public static void main( String [] args ) {
      System.out.println( new B().toString() );
    }
}
// Compile 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 'toString' definition
0

// Change A.java
class A {
   public String toString() {
      return "Nothing here";
   }
}
// Recompile 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 pourrait être trouvé ici: la spécification de la machine virtuelle JavaTM

9
répondu OscarRyz 2017-05-23 12:10:29

Eh bien, ma réponse à la question de l'intervieweur est - les membres privés ne sont pas hérités dans les sous-classes, mais ils sont accessibles à l'objet de la sous-classe ou de la sous-classe que par le biais des méthodes publiques getter ou setter ou de toute autre méthode appropriée de la classe d'origine. la pratique normale est de garder les membres privés et d'y accéder en utilisant des méthodes getter et setter qui sont publiques. Ainsi, à quoi sert de n'hériter que les méthodes getter et setter lorsque le membre privé traiter avec ne sont pas disponibles pour l'objet? Ici "hérité" signifie simplement qu'il est disponible directement dans la sous-classe pour jouer par les méthodes nouvellement introduites dans la sous-classe.

enregistrez le fichier ci-dessous en tant que ParentClass.java et essayer 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(String[] 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 la sous-classe, alors elle n'est pas directement accessible pour toute modification (signifie non hérité). Mais x peut être modifié dans la sous-classe via la méthode setX() de la classe originale comme fait dans la méthode setXofParent() ou elle peut être modifiée en utilisant L'objet ChildClass en utilisant la méthode setX() ou la méthode setXofParent () qui finalement appelle setX (). Donc ici setX() et getX () sont en quelque sorte des portes vers le membre privé x d'une classe de parent.

un autre exemple simple est Horloge superclass a des heures et des minutes en tant que membres privés et les méthodes getter et setter appropriés en tant que public. Puis vient DigitalClock comme une sous-classe D'horloge. Ici, si l' L'objet de DigitalClock ne contient pas d'heures et de membres mins puis les choses sont foirées.

5
répondu dganesh2002 2013-09-04 04:39:15

Ok, c'est un problème très intéressant, j'ai fait beaucoup de recherches et je suis arrivé à la conclusion que les membres privés d'une superclasse sont effectivement disponibles (mais pas accessibles) dans les objets de la sous-classe. Pour le prouver, voici un exemple de code avec une classe parent et une classe enfant et je suis en train d'écrire un objet de classe enfant à un fichier txt et de lire un membre privé nommé 'bhavesh' dans le fichier, prouvant ainsi qu'il est effectivement disponible dans la classe enfant mais pas accessible en raison du modificateur d'accès.

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(String[] 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) {
    }


}
}

Open MyData1.txt et rechercher le membre privé nommé 'bhavesh'. S'il vous plaît laissez-moi savoir ce que vous en pensez.

4
répondu Bhavesh Agarwal 2012-05-31 10:57:35

Il semblerait qu'une sous-classe n'hérite les champs privés dans ces champs sont utilisés dans le fonctionnement interne de la sous-classe (philosophiquement parlant). Une sous-classe, dans son constructeur, appelle le constructeur de la superclasse. Les champs privés de superclasse sont évidemment hérités par la sous-classe appelée le constructeur de superclasse si le constructeur de superclasse a initialisé ces champs dans son constructeur. C'est juste un exemple. Mais bien sûr, sans les méthodes accessor la sous-classe ne peut pas accéder aux champs privés de la superclasse (c'est comme ne pas pouvoir ouvrir le panneau arrière d'un iPhone pour sortir la batterie et réinitialiser le téléphone... mais la batterie est toujours là).

PS Une des nombreuses définitions de l'héritage que j'ai rencontré: "Héritage -- une technique de programmation qui permet à une classe dérivée d'étendre la fonctionnalité d'une classe de base, héritant tout son état (emphasis is mine) et son comportement."

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

3
répondu Flanker 2012-02-04 03:00:58

Memory Layout in Java vis-a-vis inheritance

enter image description here

bits de rembourrage / alignement et l'inclusion de la classe D'objet dans le VTABLE n'est pas considérée. Ainsi, l'objet de la sous-classe a une place pour les membres privés de la Super classe. Toutefois, il est impossible d'y accéder à partir des objets de la sous-classe...

1
répondu somenath mukhopadhyay 2017-05-06 22:47:41

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 directement accéder au champ privé de la super-classe de leurs sous-classe ?

, Alors la réponse est Non , si nous allons par le biais de la accès spécificateur de détails , il est mentionné, les membres privés ne sont accessibles que dans le la classe elle-même.

mais, si la question Est

pouvons-nous accéder au champ privé de la super-classe de leurs sous-classe ?

ce qui veut dire, peu importe ce que vous ferez pour accéder au membre privé. Dans ce cas, nous pouvons faire méthode publique dans la super-classe et vous pouvez accéder au membre privé. Donc, dans ce cas, vous créez une interface/pont pour accéder au membre privé.

autre langage OOPs comme C++, ont le friend function concept, par lequel nous pouvons accéder au membre privé d'une autre classe.

0
répondu Ravi 2012-11-30 12:53:32

nous pouvons simplement dire que lorsqu'une superclasse est héritée, les membres privés de la superclasse deviennent en fait des membres privés de la sous-classe et ne peuvent plus être hérités ou sont inaccessibles aux objets de la sous-classe.

0
répondu Aamir wani 2013-03-25 17:57:09

je devrais répondre que les champs privés en Java sont hérité. Permettez-moi de vous 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 dans un programme Bar bar = new Bar(); , alors vous verrez toujours le nombre" 2 " dans la boîte de sortie. Parce que l'entier "x" est encapsulé avec les méthodes update() et getX() , alors il peut être prouvé que l'entier est héréditaire.

la confusion est que parce que vous ne pouvez pas accéder directement l'entier "x", alors les gens soutiennent qu'il n'est pas hérité. Cependant, chaque chose non-statique dans une classe, que ce soit un champ ou une méthode, est héritée.

0
répondu Lawful Lazy 2015-02-26 23:39:50

un membre de classe privée ou un constructeur est accessible seulement dans le corps de la classe de haut niveau( §7.6 ) Cela inclut la déclaration du membre ou du constructeur. Elle n'est pas héritée par les sous-classes. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

0
répondu mimibar 2016-01-29 04:04:43

No , les champs privés ne sont pas hérités. La seule raison est que la sous-classe ne peut pas y accéder directement .

0
répondu joooohnli 2018-09-21 07:29:04

une sous-classe n'hérite pas des membres privés de sa classe d'origine. Toutefois, si la superclasse dispose de moyens publics ou protégés pour accéder à ses champs privés, ceux-ci peuvent également être utilisés par la sous-classe.

-1
répondu suprinder 2014-09-30 19:31:27

les membres privés (état et comportement) sont hérités. Ils (peuvent) influent sur le comportement et la taille de l'objet qui est instancié par la classe. Sans compter qu'ils sont très bien visibles pour les sous-classes via tous les mécanismes de cassure d'encaptulation qui sont disponibles, ou qui peuvent être assumés par leurs exécutants.

bien que l'héritage ait une définition de" defacto", 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 est juste mauvais à ce point.

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 doit être suivie est celle qui est plus sûre (ou sûre).

-2
répondu gkakas 2012-05-31 08:13:32