2012-10-23 17 views
8

Mam problem ze zrozumieniem, jak dziedziczenie działa w Javie, gdy są obecne klasy wewnętrzne. Obecnie pracuję nad czymś, w którym klasa potomna musi nieznacznie zmienić funkcjonalność wewnętrznej klasy jej rodzica. Poniżej przedstawiam prostszy, przykładowy przykład.W jaki sposób dziedziczenie Java działa przy wewnętrznych klasach?

Spodziewałem się, że ten kod wydrukuje "I am a ChildClass.InnerClass", ale zamiast tego wypisze "I am ParentClass.InnerClass". Dlaczego to? Ponadto, jeśli zmienię obiekt obj w głównym na typ ChildClass, wówczas wynik zmieni się na "I am a ChildClass.InnerClass". Dlaczego to?

Jaki jest zalecany sposób zmiany zachowania obiektu wewnętrznego klasy obiektu?

class InnerClassTest { 
    //----------------------------------------------------------------------- 
    // PARENT CLASS 
    class ParentClass { 
     public ParentClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass { 
     public void speak() { 
      System.out.println("I am a ParentClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // CHILD CLASS 
    class ChildClass extends ParentClass { 
     public ChildClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass extends ParentClass.InnerClass { 
     public void speak() { 
      System.out.println("I am a ChildClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // MAIN 
    public static void main(String[] args) { 
     ParentClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
    } 
} 

Odpowiedz

6

Zmienna nie jest "overriden", jak są metody.

Podczas połączenia oczekiwałeś, że x będzie to Child, ale to nie dlatego, że x jest zmienną, a nie metodą.

jednak zwrócić uwagę: Twój typ odniesienia jest ParentClass więc obj.x punkty przypisywać ParentClass „s InnerClass chociaż prawdziwy przykład za parentClass jest ChildClass!

W celu wyświetlenia planowanej zdanie, trzeba zmienić oznaczenie typu do ChildClass:

public static void main(String[] args) { 
     ChildClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
} 

Aby lepiej zrozumieć tę koncepcję, spróbuj określić sposób, w obu ParentClass i ChildClass klas:

public InnerClass getInnerClass(){ 
    return x; 
} 

i uczynić x prywatną.

, aby zastosować "koncepcję zastępowania".

Twój ostateczne wezwanie byłoby w tym przypadku:

ParentClass obj = (new InnerClassTest()).new ChildClass(); 
obj.getInnerClass().speak(); 

Aby zmienić zachowanie wewnętrznych klas myśleć szablonu metoda wzoru lub lepiej: Strategy wzór (ponieważ więcej szacunku DIP)

3

Zdjąć ponowna

InnerClass x; 

fr om klasy dziecka. Tak więc, będziesz miał tylko jeden x i zostanie ponownie przypisany w konstruktorze klasy potomnej. Co oznacza jeden x (odnoszący się do obiektu utworzonego w pakiecie podrzędnym).

Ukrywa się w klasie nadrzędnej. Dlatego masz dwa pola, odnoszące się do dwóch różnych obiektów.I ze względu na statyczne (w czasie kompilacji lub wczesne) wiązania w przypadku zmiennych,

ParentClass obj; 
//obj.x means the x in parent 

i

ChildClass obj; 
//obj.x means the x in child 
+0

'ParentClass obj; //obj.x oznacza x w dziecku' ?? czy miałeś na myśli ChildClass obj; – exexzian

+0

@sansix: Dokładnie. Dziękuję za edycję. –

+0

+1 za rozwiązanie – exexzian

1

w ogóle, co jest zalecanym sposobem zmiany zachowania się obiektu obiekt wewnętrzny klasy macierzystej?

Na początku zalecam użycie mniej skomplikowanego wzoru. Klasa potomna powinna zmodyfikować zachowanie rodzica poprzez przesłonięcie jego metod, więc chciałbym dodać trochę metody fabrycznej, aby nadpisać tworzenie tej zależności i zarządzać tym obiektem na szczycie hierarchii klas.

To byłoby bardziej elastyczne niż to, co proponujesz, ponieważ newInnerClass() może utworzyć instancję klasy zdefiniowanej w dowolnym miejscu, o ile ma odpowiedni interfejs.

Powiązane problemy