style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Si los atributos privados no se heredan, por que están presentes al crear una instancia de la subclase?

Ahi les va esta pregunta.

Es bien sabido ( y si no lo sabían ) que los miembros privados de una clase no se heredan.

Entonces por que cuando creamos una instancia de una subclase, los miembros privado están ahí? Me queda claro que la respuesta no es "por que fueron heredados", pero tampoco puedo obtener una explicación convincente.

  1. class A {
  2.    private int i;
  3. }
  4. class B extends A {
  5. }
  6. class UseIt {
  7.    public static void main( String ...args ) {
  8.        new B();
  9.    }
  10. }

Si pudiéramos ver el objeto creado en la linea 8, veríamos que la variable i definida en la clase A, está presente.

Alguien puede explicar por que sin decir "por que sí se heredan" ? :)

Pregunta original Does subclasses inherit private fields? [ en StackOverflow - en inglés -]

Mi no tan convincente respuesta

Saludos.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

no

si pudiéramos ver el objeto creado en la linea 8

Si mi abuelita tuviera ruedas, sería bicicleta.

Cómo podríamos ver el objeto en la linea 8? Para cualquier efecto práctico, la variable i no se hereda. No es accesible desde la clase B. Si le pones a la clase A un public int getI() { return i; } entonces puedes invocar ese método y así obtener el valor que tenga la variable i, y si le pones un public void setI(int value) { i = value; } en A, puedes modificar el valor de la variable, incluso desde B, pero no tienes acceso directo a la variable desde la clase B.

Haciendo reflection sobre B puedes encontrar la variable i pero si la intentas leer se arrojará una excepción. No es accesible.

Ahhh que con el escepticismo

Ahhh que con el escepticismo caray.

Estoy dando por hecho que el valor está ahí, pero nunca dije que fuera accesible. De hecho estoy afirmando que NO se hereda, pero no logro explicar por que SI está presente. El como obtenerla no es lo importante aquí, sino el por que está presente.

De todas formas ( nomás para permitir que la pregunta pueda ser contestada ) aquí está la prueba de que el valor si esta presente usando Java VisualVM que viene en todas las distribuciones de Sun Oracle de Java

Ahora, confirmando con las imagenes que el valor si está ( La foto de la abuelita-bicicleta queda pendiente o_O )

¿Por que está la variable i presente, si no es heredada?

Imagen de ezamudio

por acceso

Está presente en la subclase, porque si la superclase tiene métodos que la utilicen, al invocarse con el contexto de la subclase necesitan ver esa variable, pero solamente como métodos de la superclase la puedan accesar. Una optimización de runtime nada mas.

Imagen de bferro

Claro que los atributos se "heredan"

La visibilidad en los atributos no afecta la herencia de los mismos en las clases derivadas. Todo atributo codificado en cualquier lugar de la jerarquía de clases, es heredado por las clases derivadas y forma parte del estado de los objetos de esas clases derivadas, aunque los métodos de esas clases no tengan acceso a los atributos privados de sus clases bases.

Tampoco se trata de un problema de optimización de runtime. Se trata en esencia de usar la herencia correctamente como una de las técnicas posibles para describir de manera incremental un concepto usando el principio de generalización/ (especialización y/o extensión).

Al codificar atributos privados en una clase, estamos asumiendo que todo lo que tenga que ver con administrar el estado de los objetos que está representado por esos atributos, puede codificarse en esa clase y entonces conviene "ocultarlos" al resto de las clases que están más abajo en la jerarquía de herencia. Es una decisión nada trivial y que con frecuencia sucede que necesitamos cambiar esa visibilidad.

Algunos lo resuelven con getters y setters protegidos para que las clases derivadas puedan entonces manipular esos atributos, pero se abusa mucho de eso, lo que en ocasiones resulta en jerarquías de herencia mal diseñadas.

Imagen de benek

¿Mal definido?

¿Entonces está mal la definición? El tutorial de Sun Oracle dice al respecto:

Private Members in a Superclass

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

Ese "does not inherit" en realidad no es tal, las variables sí se heredan pero no es posible accederlas directamente.

¿Es correcto?

¿?

Alguien responda esto. Tengo la misma duda que benek.

Imagen de ezamudio

es correcto.

public class Padre {
  private int priv;
  public void setPriv(int value) { priv=value; }
  public int getPriv() { return priv; }
}

public class Hijo extends Padre {
  public void noCompila() {
    priv=0;
  }
  public void siCompila() {
    setPriv(0);
  }
}

La clase Padre define la variable privada priv. Esa variable no se hereda a la clase Hijo. Pero los accesores de priv son públicos, por lo que Hijo sí los puede invocar. El método siCompila invoca al método setPriv, que al no estar sobreescrito en la subclase, se invoca directamente en la clase Padre y se modifica el valor de priv (digamos que las instancias de Hijo tienen su propio priv pero no lo pueden ver directamente).

Imagen de eneida

Agradecida

Sé que hace tiempo de este post, pero agradezco a todos su aportación, ha sido muy constructivo para mí y ha resuelto mis dudas.

Gracias.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">