Java: uso del método de clase principal para acceder a la variable de clase secundaria

Tengo el siguiente escenario :

public class A {

    private int x = 5;

    public void print()
    {
        System.out.println(x);
    }
}


public class B extends A {

    private int x = 10;

    /*public void print()
    {
        System.out.println(x);      
    }*/

    public static void main(String[] args) {
        B b = new B();
        b.print();
    }

}

Al ejecutar el código, la salida es: 5.

¿Cómo acceder a la variable (x) de la clase secundaria (B) a través del método de la clase principal?

¿Se podría hacer esto? sin anulando el método print() (es decir, descomentándolo en B)?

[Esto es importante porque al anular tendremos que volver a escribir todo el código para el método print()]

EDITADO

Más aclaraciones: -

  • El motivo de la pregunta es usar el valor de una variable privada de clase secundaria de su método de clase principal. Esto no requiere cambiar el valor de la variable privada de la clase principal para lograr el resultado deseado.
  • Sin embargo, las respuestas publicadas aquí me llevaron a la respuesta deseada, que publiqué a continuación.

(Gracias a todos por su tiempo y ayuda)

preguntado el 04 de julio de 12 a las 02:07

Cuando quieres imprimir la variable de B x, tienes la intención de x ser diferente de A x, o deben ser iguales? -

@WeiHao del código es obvio que el x in A es ser 5, el de B es tener 10 años. Quiere B.print() a la salida 10, porque no está contento con una salida de 5. Por lo tanto, espera que sean diferentes. -

@Jayant No se trata de que el padre no tenga información, no la tiene. El problema es que el valor de x no se anula durante la creación de B. -

Mi principal preocupación es que, aquí, el niño no puede reutilizar el código de la clase principal. ¿Se podría reutilizar este código? -

@Jayant, el código en la clase principal se puede reutilizar, solo mire mi respuesta :). Tu problema es que el valor de x no se actualiza cuando B se crea, porque los valores predeterminados solo se evalúan una vez. -

5 Respuestas

class A {
    private int x = 5;

    protected int getX() {
        return x;
    }

    protected void setX(int x) {
        this.x = x;
    }

    public void print() {
        // getX() is used such that 
        // subclass overriding getX() can be reflected in print();
        System.out.println(getX());
    }
}

class B extends A {
    public B() {
        // setX(10);  // perhaps set the X to 10 in constructor or in main
    }

    public static void main(String[] args) {
        B b = new B();
        b.setX(10);
        b.print();
    }
}

EDITADO

A continuación se muestra una respuesta general que usa una clase y un método abstractos para resolver un escenario similar:

abstract class SuperA {
    protected abstract Object getObj();

    public void print() {
        System.out.println(getObj());
    }
}

class A extends SuperA {
    @Override
    protected Object getObj() {
        // Your implementation
        return null; // return what you want
    }
}

class B extends A {
    @Override
    protected Object getObj() {
        // Your implementation
        return null; // return what you want
    }

    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}

Respondido 04 Jul 12, 04:07

Buena solución integral. Esto es bastante OOP =D. Además, muy parecido a C#. - usuario1241335

@Shingetsu, gracias, pero no sé nada de C#, planeo aprenderlo pero mi trabajo no me lo permite... - Victor Wong

básicamente, C# es solo una versión elegante de Java. Si ya conoces bien Java no tendrás muchos problemas para aprenderlo, aunque conocer .NET y C++ te vendría bien =D. - usuario1241335

Esto funcionaría bien. Pero en realidad supera el motivo de la pregunta. Lo que se requiere es usar el valor de la variable de la clase secundaria en una función de clase principal. - Jayant

Luego, simplemente puede anular el método getX() y devolver el valor requerido. - Victor Wong

Después de leer todas las respuestas publicadas aquí, obtuve lo que estaba buscando. La siguiente es lo que creo que es la mejor respuesta para mi pregunta:

public class A {
    private int x = 5;    
    protected int getX(){
        return x; 
    }    
    public void print(){
        System.out.println(getX());
    }
}
public class B extends A {
    private int x = 10;
    protected int getX(){
        return x; 
    }  
    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}

Configurar un getter protegido y anularlo es mejor que anular el print() método en sí mismo, ya que podría haber cualquier otro método enorme en lugar del método de impresión que podría necesitar acceder al valor de la(s) variable(s) de clase secundaria.

Respondido 10 Abr '15, 07:04

@kakacii Sí, aunque la respuesta de VictorWong no responde la pregunta con precisión, a las personas les resulta más útil. He cambiado mi elección. Gracias :) - Jayant

@Jayant No puedo ver ninguna diferencia entre mi solución general (no la primera, sino la editada) y su respuesta aquí, excepto que reemplaza obj con x. Sin ofender, pero quiero saber por qué mi solución no es lo suficientemente precisa. - Victor Wong

Para resolver su pregunta, debe definir los campos en la clase principal A como protegidos (por lo que se heredará en la clase secundaria) y establecer el valor de campo x dentro del constructor en la clase secundaria B. El método de impresión también se hereda de Una clase para que pueda invocarla directamente desde la clase principal.

Espero que esto pueda ayudarte.

public class A 
{
    // fields declaration 
    protected int x = 5;

    public void print()
    {
        System.out.println(x);
    }
}



public class B extends A 
{

    public B()
    {
        // set child x value. The field have been defined in the parent class
        x = 10;
    }

    public static void main(String[] args) 
    {
        A a = new A();
        a.print(); // print 5

        B b = new B();
        b.print(); // print 10
    }

}

Respondido 01 ago 14, 16:08

Siempre puedes agregarlo al constructor:

public class B extends A {

    //this line is unnecessary: private int x = 10;

    /*public void print()
    {
        System.out.println(x);      
    }*/

    public B()
    {
        x=10;
    }


    public static void main(String[] args) {
        B b = new B();
        b.print();
    }

}

La razón por la que no funcionará mientras lo intenta es que los valores predeterminados solo se evalúan una vez. Entonces, cuando es 5 predeterminado en A, permanece 5 aunque haya usado 10 predeterminado en B.

Respondido 04 Jul 12, 02:07

En primer lugar, cambiar x en el constructor de B no funcionará si la visibilidad de x es privada. En segundo lugar, incluso si protegemos la visibilidad de x, cambiaría el valor de la variable x en la clase principal. Lo que se requiere no es cambiar el valor de la variable en la clase principal, sino usar el valor de la variable de la clase secundaria. - Jayant

@Jayant la variable de clase secundaria NO EXISTE. Haces una variable en el padre, le das un valor predeterminado. Los valores predeterminados se evalúan una vez. Das LA MISMA VARIABLE otro valor predeterminado en B, pero el valor por defecto ya ha sido evaluado en A. Cuando haces B, IL 1st evalúa el valor predeterminado para x in A, entonces x in B, pero desde x ya fue evaluado en A, La línea de private int x = 10; no hace absolutamente nada. - usuario1241335

No entiendo lo que estás tratando de decir. Claramente, la declaración private int x = 10 en la clase B asigna algo de memoria nueva para la variable x en la clase B y es completamente independiente de la variable x en A. - Jayant

@Jayant NO es completamente independiente de la variable en A. Todo lo contrario, la variable en A es privado, y como tal se hereda. La declaración private in x = 10; no crea una nueva variable x. Imagina escribir: public class A { private int x = 5; private int x = 10; }. ¿No tiene sentido? Esa es la misma situación. los campos privados se heredan (pero no se puede acceder a ellos). por lo que la declaración private int x = 10; en realidad no hace nada en absoluto. - usuario1241335

@Jayant desea crear una variable completamente nueva en la clase secundaria, o solo usar la de la clase principal. No hay término medio". En el 1er caso, hay que cambiar el nombre. En este último caso, tienes que hacerlo protegido. - usuario1241335

Debe exponer un getter para el valor que desea y anularlo en la clase secundaria.

Al igual que:

public class A {

    private int x = 5;

    public void print()
    {
        System.out.println(getX());
    }

    protected void setX(int x)
    {
        this.x = x;
    }

    protected int getX()
    {
        return x;
    }

}


public class B extends A {

    /*public void print()
    {
        System.out.println(x);      
    }*/

    public B()
    {
        setX(10);
    }

    public static void main(String[] args) {
        B b = new B();
        b.print();
    }

}

Respondido 04 Jul 12, 19:07

Eso también funciona, aunque ¿qué pasa si x tiene que cambiarse en un punto? Esto se limita al ejemplo dado. - usuario1241335

Haz un setter de X también entonces. - Victor Wong

@VictorWong Esto no es un captador real, la variable no está realmente allí. - usuario1241335

Esta es una gran respuesta (resuelve el problema). Sería bueno declarar una variable privada y devolverla en el método getX() en lugar de devolver los valores directamente. Si lo permite, podría editar su respuesta para hacer lo anterior (y aceptarla). - Jayant

actualizo la respuesta para proporcionar un setter que usa la subclase en su constructor. Esto debería tener el mismo efecto. - Savvas Dalkitsis

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.