2012-07-04 10 views
12

Mam następujący scenariusz:Java: Stosując metodę klasy nadrzędnej dostęp do klasy zmiennej dziecko

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(); 
    } 

} 

Na wykonywanie kodu, wyjście jest: 5.

Jak uzyskać dostęp do klasy dziecięcej (B) zmienna (x) za pomocą metody klasy nadrzędnej?

Czy można to zrobić bez nadpisując metodę print() (to znaczy odkomentuj ją w B)?

[Jest to ważne, ponieważ na nadrzędnych będziemy musieli przepisać cały kod dla wydruku() metody ponownie]

EDITED

więcej wyjaśnień: -

  • Motywem pytanie polega na użyciu wartości zmiennej prywatnej klasy potomnej z jej metody klasy nadrzędnej. Nie wymaga to zmiany wartości zmiennej prywatnej klasy macierzystej, aby osiągnąć pożądany wynik.
  • Odpowiedzi zamieszczone tutaj doprowadziły mnie jednak do mojej pożądanej odpowiedzi, którą zamieściłem poniżej.

(Dzięki wszystkim za poświęcony czas i pomoc)

+0

Kiedy chcesz wydrukować zmienną B 'x', czy chcesz, aby' x' różniło się od 'X' A, czy powinno być takie samo? –

+0

@WeiHao od kodu jest oczywiste, że 'x' w' A' ma być 5, to w 'B' ma być 10. On chce' B.print() 'wypisać 10, ponieważ nie jest szczęśliwy z wynikiem 5. Tak więc oczekuje, że będą inni. –

+0

@Jayant Nie chodzi o to, że rodzic nie ma informacji, ale nie ma. Problem polega na tym, że wartość 'x' nie jest nadpisywana podczas tworzenia' B'. –

Odpowiedz

8
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(); 
    } 
} 

EDITED

Poniżej znajduje się ogólna odpowiedź za pomocą klasy abstrakcyjnej i sposób rozwiązać podobny scenariusz:

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(); 
    } 
} 
+0

Ładne i wszechstronne rozwiązanie. To jest dość OOP = D. Również bardzo podobne do C#. –

+0

@Shingetsu, Dzięki, ale nic nie wiem o C#, mam zamiar się tego nauczyć, ale moja praca nie pozwala ... –

+0

zasadniczo, C# to tylko elegancka wersja Java. Jeśli znasz już Javę, nie będziesz miał problemu z jej nauką, chociaż wiedząc, że .NET i C++ przydadzą się jako D =. –

0

należy wystawiać getter dla wartości chcesz i zastąpić że w klasie podrzędnej.

tak:

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(); 
    } 

} 
+0

To też działa, ale co, jeśli x trzeba zmienić w jednym punkcie? Jest to ograniczone do podanego przykładu. –

+0

Zrób także setera X. –

+0

@VictorWong To nie jest prawdziwy getter, zmienna nie istnieje. –

0

Zawsze możesz dodać go do konstruktora:

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(); 
    } 

} 

Powodem nie będzie działać jak spróbować to, że wartości domyślne się ocenić tylko raz. Więc kiedy jest domyślnym 5 w A, to pozostaje 5, mimo że używany domyślnie 10 w B.

+0

Po pierwsze, zmiana x w konstruktorze B nie zadziała, jeśli widoczność x jest prywatna. Po drugie, nawet jeśli sprawimy, że widoczność x będzie chroniona, zmieni się wartość zmiennej x w klasie nadrzędnej. Wymagana jest nie zmiana wartości zmiennej w klasie nadrzędnej, ale użycie wartości zmiennej klasy potomnej. – Jayant

+0

@Dzień zmienną klasy podrzędnej *** NIE MA ISTNIEJE ***. Tworzysz zmienną w rodzicu, nadasz mu wartość domyślną. Wartości domyślne są szacowane jeden raz. Dajesz *** SAME VARIABLE *** kolejną domyślną wartość w 'B', ale domyślna wartość została już oceniona w' A'. Kiedy tworzysz 'B', IL 1 ocenia domyślną wartość dla' x' w 'A', następnie' x' w 'B', ale ponieważ' x' jest już ocenione w 'A', wiersz' private int x = 10; 'nie robi absolutnie nic. –

+0

Nie rozumiem, co próbujesz powiedzieć. Oczywiście instrukcja private int x = 10 w klasie B przydziela trochę pamięci dla zmiennej x w klasie B i jest całkowicie niezależna od zmiennej x w A. – Jayant

6

Po przeczytaniu wszystkich zamieszczonych tutaj odpowiedzi uzyskałem to, czego szukałem. Poniżej to, co czuję jest najlepszą odpowiedzią na moje pytanie:

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(); 
    } 
} 

Konfigurowanie chronionej getter i przesłanianie to lepiej niż nadrzędne samej metody print(), ponieważ nie może być jakakolwiek inna ogromny metoda w miejsce metoda drukowania, która może wymagać dostępu do wartości zmiennych klasy potomnej.

+0

Powinieneś naprawdę wybrać odpowiedź @VictorWong jako najlepszą odpowiedź ... – kakacii

+0

@kakacii Tak, chociaż odpowiedź VictorWonga nie odpowiada dokładnie na pytanie, ludzie uważają ją za bardziej użyteczną. Zmieniłem swój wybór. Dzięki :) – Jayant

+0

@Jayant Nie widzę żadnej różnicy między moim ogólnym rozwiązaniem (nie pierwszym, ale edytowanym) a twoją odpowiedzią tutaj, z wyjątkiem tego, że zamieniasz 'obj' na' x'. Bez obrazy, ale chcę wiedzieć, dlaczego moje rozwiązanie nie jest wystarczająco precyzyjne. –

1

Aby rozwiązać swoje pytanie, należy zdefiniować pola w klasie nadrzędnej A, które są chronione (więc będą dziedziczone w klasie potomnej) i ustawić wartość pola x wewnątrz konstruktora w klasie podrzędnej B. Metoda drukowania jest również dziedziczone z klasy A, więc możesz wywołać ją bezpośrednio z klasy nadrzędnej.

Mam nadzieję, że to może ci pomóc.

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 
    } 

} 
Powiązane problemy