¿Las subclases heredan campos privados?


Esta es una pregunta de entrevista.

¿Las subclases heredan privado ¿fields?

Respondí "No", porque no podemos acceder a ellos usando la "forma normal de OOP". Pero el entrevistador piensa que son heredados, porque podemos acceder a tales campos indirectamente o utilizando la reflexión y todavía existen en el objeto.

Después de regresar, encontré la siguiente cita en el javadoc :

Miembros privados en una Superclase

A subclase no hereda el privado miembros de su clase madre.

¿Conoce algún argumento para la opinión del entrevistador?

Author: Peter O., 2011-01-17

17 answers

La mayor parte de la confusión en la pregunta/respuestas aquí rodea la definición de Herencia.

Obviamente, como @DigitalRoss explica un OBJETO de una subclase debe contener los campos privados de su superclase. Como afirma, no tener acceso a un miembro privado no significa que no esté allí.

Sin embargo. Esto es diferente a la noción de herencia para una clase. Como es el caso en el mundo java, donde hay una cuestión de semántica el árbitro es el Java Especificación del idioma (actualmente 3a edición).

Como dice la JLS ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

Miembros de una clase que se declaran privados no son heredados por subclases de esa clase. Solo miembros de una clase declarada protegida o públicos son heredados por subclases declarado en un paquete que no sea el uno en el que se declara la clase.

Esto aborda el exacto pregunta planteada por el entrevistador :" do subCLASSES inherit private fields". (cursiva añadida por mí)

La respuesta es No. No lo hacen. Los OBJETOS de subclases contienen campos privados de sus superclases. La subclase en sí no tiene NOCIÓN de campos privados de su superclase.

¿Es semántica de naturaleza pedante? Sí. ¿Es una pregunta útil para una entrevista? Probablemente no. Pero la JLS establece la definición para el mundo Java, y lo hace (en este caso) inequívoca.

EDITADO (se eliminó una cita paralela de Bjarne Stroustrup que debido a las diferencias entre java y c++ probablemente solo se suman a la confusión. Dejaré que mi respuesta descanse en el JLS:)

 208
Author: robert_x44,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-11 12:01:04

Es importante darse cuenta de que mientras hay dos clases, solo hay un objeto.

Así que, sí, por supuesto que heredó los campos privados. Son, presumiblemente, esenciales para la funcionalidad adecuada del objeto, y mientras que un objeto de la clase padre no es un objeto de la clase derivada, una instancia de la clase derivada es en su mayoría definitivamente una instancia de la clase padre. No podría ser eso sin todos los campos.

No, no puedes accede directamente a ellos. Sí, son heredados. Ellos tienen ser.

, Es una buena pregunta!


Actualizar:

Err,"No"

Bueno, supongo que todos aprendimos algo. Dado que el JLS originó el texto exacto "no heredado", es correcto responder "no". Dado que la subclase no puede acceder o modificar los campos privados, entonces, en otras palabras, no se heredan. Pero realmente es solo uno object, realmente contiene los campos privados, por lo que si alguien toma la redacción JLS y tutorial de la manera equivocada, será bastante difícil de entender OOP, objetos Java, y lo que realmente está sucediendo.

Actualizar a actualizar:

La controversia aquí implica una ambigüedad fundamental: ¿qué se está discutiendo exactamente? El objeto ? O estamos hablando en algún sentido de la clase misma? Se permite mucha latitud cuando se describe la clase en lugar del objeto. Así que la subclase no hereda campos privados, pero un objeto que es una instancia de la subclase ciertamente contiene los campos privados.

 67
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 19:04:52

No. Los campos privados no se heredan... y por eso se inventó Protected. Es por diseño. Supongo que esto justificaba la existencia del modificador protegido.


Ahora vamos a los contextos. ¿Qué quieres decir con heredado inherited si está allí en el objeto creado a partir de la clase derivada? sí, lo es.

Si quiere decir puede ser útil para la clase derivada. Bueno, no.

Ahora, cuando se llega a la programación funcional el campo privado de super clase no se hereda en una forma significativa para la subclase . Para la subclase, un campo privado de superclase es lo mismo que un campo privado de cualquier otra clase.

Funcionalmente, no se hereda. Pero idealmente, lo es.


OK, acabo de mirar en Java tutorial citan esto:

Miembros privados en una Superclase

Una subclase no hereda los miembros privados de su clase padre. Sin embargo, si la superclase tiene métodos públicos o protegidos para acceder a sus campos privados, estos también pueden ser utilizados por la subclase.

Refiérase a: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

Estoy de acuerdo, que el campo está ahí. Pero, subclase no obtiene ningún privilegio en ese campo privado. Para una subclase, el campo privado es el mismo que cualquier campo privado de cualquier otra clase.

creo que es puramente cuestión de punto de vista. Usted puede moldear el argumento de cualquier lado. Es mejor justificar en ambos sentidos.

 

 18
Author: Nishant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-27 09:53:47

Depende de su definición de "heredar". ¿La subclase todavía tiene los campos en memoria? Definitivamente. Puede acceder a ellos directamente? No. Son solo sutilezas de la definición; el punto es entender lo que realmente está sucediendo.

 10
Author: Mehrdad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-17 17:36:21

Demostraré el concepto con código. Las subclases EN REALIDAD heredan las variables privadas de la super clase. El único problema es que no son accesibles a la objetos secundarios a menos que proporcione getters y setters públicos para las variables privadas en la súper clase.

Considere dos clases en el volcado de paquetes. El Niño extiende al Padre.

Si recuerdo correctamente, un objeto hijo en la memoria consta de dos regiones. Una es la parte padre solamente y la otra es la parte del niño solamente. Un niño puede acceder a la privada sección en el código de su padre solo a través de un método público en el padre.

Piénsalo de esta manera. El padre de Borat, Boltok, tiene una caja fuerte que contiene 100.000 dólares. No quiere compartir su caja fuerte variable "privada". Por lo tanto, él no proporciona una llave para la caja fuerte. Borat hereda la caja fuerte. Pero, ¿de qué sirve si ni siquiera puede abrirlo ? Si sólo su papá había proporcionado la llave.

Padre -

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

Niño -

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
Author: Borat Sagdiyev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 00:46:58

No. No lo heredan.

El hecho de que alguna otra clase pueda usarlo indirectamente no dice nada sobre la herencia, sino sobre la encapsulación.

Por ejemplo:

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?
     }
}

También puede obtener el valor de count dentro de UseIt mediante reflexión. No significa que lo heredes.

ACTUALIZACIÓN

Aunque el valor está ahí, no es heredado por la subclase.

Por ejemplo, una subclase definida como:

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?           
     }
}

Esto es exactamente lo mismo situación como primer ejemplo. El atributo countestá oculto y no heredado por la subclase en absoluto. Aún así, como señala DigitalRoss, el valor está ahí, pero no por medio de la herencia.

Ponlo de esta manera. Si tu padre es rico y te da una tarjeta de crédito, todavía puedes comprar cosas con su dinero, pero no significa que tengas heredado todo ese dinero, ¿verdad?

Otra actualización

Aunque es muy interesante, para saber por qué el atributo está allí.

Francamente no tengo el término exacto para describirlo, pero es la JVM y la forma en que funciona lo que carga también la definición padre "no heredada".

En realidad podríamos cambiar el padre y la subclase seguirá funcionando.

Por ejemplo:

//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

Supongo que el término exacto se puede encontrar aquí: La Especificación de la Máquina Virtual JavaTM

 9
Author: OscarRyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:29

Bueno, mi respuesta a la pregunta del entrevistador es - Los miembros privados no se heredan en subclases, pero son accesibles para subclases o objetos de subclases solo a través de métodos públicos getter o setter o cualquier método apropiado de la clase original. La práctica normal es mantener a los miembros privados y acceder a ellos utilizando los métodos getter y setter que son públicos. Entonces, ¿cuál es el punto en heredar solo los métodos getter y setter cuando el miembro privado con el que tratan no es disponible para el objeto? Aquí 'heredado' simplemente significa que está disponible directamente en la subclase para jugar con los métodos recién introducidos en la subclase.

Guarde el siguiente archivo como ParentClass.java y pruébelo usted mismo ->

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 intentamos usar la variable privada x de ParentClass en el método de SubClase, entonces no es directamente accesible para ninguna modificación (significa no heredado). Pero x se puede modificar en SubClase a través del método setX () de la clase original como se hace en setXofParent() método O puede ser modificado usando el objeto ChildClass usando el método setX () o el método setXofParent () que en última instancia llama a setX (). Así que aquí setX() y getX () son una especie de puertas al miembro privado x de una ParentClass.

Otro ejemplo simple es Clock superclass tiene horas y minutos como miembros privados y los métodos getter y setter apropiados como públicos. Luego viene DigitalClock como una subclase de Reloj. Aquí, si el objeto DigitalClock no contiene miembros de horas y minutos, entonces las cosas son la pata.

 5
Author: dganesh2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-04 04:39:15

Ok, este es un problema muy interesante que investigué mucho y llegué a la conclusión de que los miembros privados de una superclase están efectivamente disponibles (pero no accesibles) en los objetos de la subclase. Para probar esto, aquí hay un código de muestra con una clase padre y una clase hijo y estoy escribiendo un objeto de clase hijo a un archivo txt y leyendo un miembro privado llamado 'bhavesh' en el archivo, por lo tanto, demostrando que está disponible en la clase hijo pero no accesible debido al acceso modificador.

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) {
    }


}
}

Abre MyData1.txt y buscar el miembro privado llamado 'bhavesh'. Por favor, háganme saber lo que piensan.

 4
Author: Bhavesh Agarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-31 10:57:35

Parecería que una subclase hereda los campos privados en que estos mismos campos son utilizados en el funcionamiento interno de la subclase (filosóficamente hablando). Una subclase, en su constructor, llama al constructor de superclase. Los campos privados de superclass son obviamente heredados por la subclase que llama al constructor de superclass si el constructor de superclass ha inicializado estos campos en su constructor. Eso es solo un ejemplo. Pero por supuesto sin los métodos del accesor la subclase no puede acceder a los campos privados de la superclase (es como no poder hacer estallar el panel posterior de un iPhone para sacar la batería para restablecer el teléfono... pero la batería sigue ahí).

PS Una de las muchas definiciones de herencia que he encontrado: "Herencia technique una técnica de programación que permite a una clase derivada extender la funcionalidad de una clase base, heredando todo su ESTADO (el énfasis es mío) y comportamiento."

Los campos privados, incluso si no accesibles por la subclase, son el estado heredado de la superclase.

 3
Author: Flanker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-04 03:00:58

Diseño de memoria en Java vis-a-vis herencia

introduzca la descripción de la imagen aquí

Los bits de relleno/Alineación y la inclusión de la Clase de objeto en la tabla V no se consideran. Así que el objeto de la subclase tiene un lugar para los miembros privados de la superclase. Sin embargo, no se puede acceder desde los objetos de la subclase...

 1
Author: somenath mukhopadhyay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-06 22:47:41

Creo que la respuesta depende totalmente de la pregunta que se ha hecho. Quiero decir, si la pregunta es

Podemos directamente acceder al campo privado de la super-clase desde sus sub-clase ?

Entonces la respuesta es No, si pasamos por los detalles del especificador de acceso , se menciona, los miembros privados son accesibles solo dentro de la propia clase.

Pero, si la pregunta es

Podemos acceder al campo privado de la super-clase de sus sub-clase ?

Lo que significa, no importa, lo que va a hacer para acceder al miembro privado. En ese caso, podemos hacer método público en la super-clase y se puede acceder al miembro privado. Por lo tanto, en este caso está creando una interfaz/puente para acceder al miembro privado.

Otro lenguaje OOPs como C++, tiene el friend function concepto, por el cual podemos acceder al miembro privado de otra clase.

 0
Author: Ravi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 12:53:32

Simplemente podemos afirmar que cuando una superclase es heredada, entonces los miembros privados de la superclase realmente se convierten en miembros privados de la subclase y no pueden ser heredados o son inaccesibles a los objetos de la subclase.

 0
Author: Aamir wani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-25 17:57:09

Tendría que responder que los campos privados en Java son heredados. Permítanme demostrar:

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 ejecuta un programa Bar bar = new Bar();, siempre verá el número "2" en el cuadro de salida. Debido a que el entero "x" está encapsulado con los métodos update() y getX(), entonces se puede probar que el entero es heredado.

La confusión es que debido a que no se puede acceder directamente al entero "x", entonces la gente argumenta que no es heredado. Sin embargo, cada no estático cosa en una clase, ya sea campo o método, se hereda.

 0
Author: Lawful Lazy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 23:39:50

Un miembro o constructor de clase privada es accesible solo dentro del cuerpo de la clase de nivel superior (§7.6) que incluye la declaración del miembro o constructor. No es heredado por subclases. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

 0
Author: mimibar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-29 04:04:43

No , los campos privados no se heredan. La única razón es que la subclase no puede acceder a ellos directamente .

 0
Author: joooohnli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-21 07:29:04

Una subclase no hereda los miembros privados de su clase padre. Sin embargo, si la superclase tiene métodos públicos o protegidos para acceder a sus campos privados, estos también pueden ser utilizados por la subclase.

 -1
Author: suprinder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-30 19:31:27

Los miembros privados (estado y comportamiento) se heredan. Pueden afectar el comportamiento y el tamaño del objeto instanciado por la clase. Sin mencionar que son muy visibles para las subclases a través de todos los mecanismos de ruptura de encaptulación que están disponibles, o pueden ser asumidos por sus implementadores.

Aunque la herencia tiene una definición "defacto", definitivamente no tiene ningún vínculo con los aspectos de "visibilidad", que son asumidos por las respuestas "no".

Entonces, no hay necesito ser diplomático. JLS está equivocado en este punto.

Cualquier suposición de que no son "heredadas" es insegura y peligrosa.

Así que entre dos definiciones de hecho (parcialmente) en conflicto (que no repetiré), la única que debe seguirse es la que es más segura (o segura).

 -2
Author: gkakas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-31 08:13:32