Dostęp i korzystanie z obiektów innych klas

0

Cześc,

Chciałbym dobrze zrozumieć procesy związane z dostępem do obiektów innych klas. Temat wydaje się prosty, ale zawsze mam wrażenie, że czegoś nie wiem.
Spójrzmy na przykład poniżej. Mam klasę Green i klasę Blue, która dziedziczy po klasie Green. W metodzie "metoda1" mam po jednym zainicjalizowanym obiekcie obu klas. Zadeklarowana jest także metoda getGreen() zwracająca obiekt green. To co chcę tutaj zrobić to uzyskać dostęp do obiektu green przez klasę Blue. Kod poniżej ma wypisać dwie linijki z adresem obiektu green, bezpośrednio z klady Green a następnie z klasy Blue poprzez wywołanie metody getGreen(). Mógłby mi ktoś wytłumaczyć dlaczego po kompilacji druga linijka zwraca null? Co powoduje, że getGreen() wywołana w klasie Blue zwraca jedynie pustą zmienną green?
Czy jest możliwe korzystanie z obiektu green przez klasę Blue bez przesyłania go jako argumentu do metody w klasie Blue? Byłbym również bardzo wdzięczny za polecenie dobrych materiałów, które dobrze opisują tego typu problemy.

public class Green   {

	private Green green;
	private Blue blue;	
	
public void metoda1() {
	
	green = new Green();
	blue = new Blue();
	
	System.out.println(getGreen());
	
	blue.metoda2();
}

public Green getGreen() {
	return green;
}


public static void main(String[] args) {
	
 Green obj = new Green();
 obj.metoda1();
	
}}
public class Blue extends Green {
		
	public void metoda2() {
	
		System.out.println(getGreen());
		
	}
}
0

Obydwie instancje Twoich klas są niezależne od siebie - mają niezależny zestaw pól, niezależnie od tego czy dziedziczą po sobie, czy też nie.

Podobny przypadek, na którym być może lepiej będzie zobrazowana sytuacja:

abstract class Entity {
  private int health;

  void setHealth(int value) {
    this.health = value;
  }

  int getHealth() {
    return this.health;
  }
}

class Hero extends Entity {
}

class Monster extends Entity {
}

/* ... */

pubilc static void main() {
  Hero = new Hero();
  Monster = new Monster();

  hero.setHealth(10);
  monster.setHealth(20);

  hero.getHealth(); // zwróci 10
  monster.getHealth(); // zwróci 20
}

Mimo że zarówno Hero jak i Monster dziedziczą po Entity, w którym znajduje się pole health, obydwie instancje mają niezależny zestaw pól - modyfikacja jednego obiektu nie wpływa na drugi.

To samo dzieje się u Ciebie - zamień tylko health na green.

1

Cała ta hierarchia nie ma sensu, ale zalecam zrobić te pola klasy final i inicjalizować konstruktorem i wtedy IDE samo ci zasugeruje że brakuje ci inicjalizacji pól odziedziczonych.

0
Patryk27 napisał(a):

Mimo że zarówno Hero jak i Monster dziedziczą po Entity, w którym znajduje się pole health, obydwie instancje mają niezależny zestaw pól - modyfikacja jednego obiektu nie wpływa na drugi.

To samo dzieje się u Ciebie - zamień tylko health na green.

Dzięki za odpowiedzi, chodzi mi jednak o coś trochę innego. Nawiązując do klas Monster i Hero czy jest możliwe aby klasa Monster mogła użyć obiektu Hero w taki sam sposób jak klasa Hero czyli hero.setHealth(10); ?

W moim przykładzie klasa Blue próbuje użyć obiektu Green poprzez użycie gettera GetGreen(). Zwracany jest jednak null, który prowadzi później do NullPointerException. I nie rozumiem za bardzo dlaczego metoda zwraca pustą zmienną green. Jeśli natomiast w getterze getGreen() umieszczę inicjalizację green = new Green(); to owszem to działa i klasa Blue korzysta z tego obiektu, ale zainicjalizowany tutaj obiekt green wskazuje na inny adres niż obiekt green zainicjalizowany wcześniej w metodzie Green. Czy jest możliwe aby getGreen() zwracał do metody Blue ten ten sam obiekt green utworzony w metodzie Green?
Przepraszam jeśli zbyt haotycznie to opisałem. =)

1
SlowSheep napisał(a):

W moim przykładzie klasa Blue próbuje użyć obiektu Green poprzez użycie gettera GetGreen(). Zwracany jest jednak null, który prowadzi później do NullPointerException. I nie rozumiem za bardzo dlaczego metoda zwraca pustą zmienną green.

Dla mnie na przykład zaskakujące jest, że spodziewasz się, że ten wyjątek nie poleci ;-) Więc może będzie łatwiej wskazać gdzie się mylisz w swoim rozumowaniu, jeśli to rozumowanie wytłumaczysz.
Więc jak Ty to widzisz - dlaczego według Ciebie getGreen() który wywołujesz w Blue.metoda2() powinien zwrócić coś innego, niż null? Skąd Twoim zdaniem miałoby się wziąć coś w polu green w obiekcie blue?

1
public void metoda1() {  //1

    green = new Green(); //2
    blue = new Blue(); //3

    System.out.println(getGreen());

    blue.metoda2();  //4
}

blue z 3 (czyli obj.blue) ma własne pole green (obj.blue.green) inne niż to z 2 (obj.green). 4 zwraca null bo obj.blue.green jest inicjowane dopiero w obj.blue.metoda1().

Jeżeli chcesz w 4 zwrócić green z 2 to przypisz go wcześniej np: blue.setGreen(green);.

0
Delor napisał(a):
public void metoda1() {  //1

    green = new Green(); //2
    blue = new Blue(); //3

    System.out.println(getGreen());

    blue.metoda2();  //4
}

blue z 3 (czyli obj.blue) ma własne pole green (obj.blue.green) inne niż to z 2 (obj.green). 4 zwraca null bo obj.blue.green jest inicjowane dopiero w obj.blue.metoda1().

Jeżeli chcesz w 4 zwrócić green z 2 to przypisz go wcześniej np: blue.setGreen(green);.

Dzięki za to wytłumaczenie, z jakiegoś względu kompletnie umknęło mi to, że cały czas działam tak naprawdę w obszarze obiektu o nazwie obj.

Skok Napięcia napisał(a):
SlowSheep napisał(a):

W moim przykładzie klasa Blue próbuje użyć obiektu Green poprzez użycie gettera GetGreen(). Zwracany jest jednak null, który prowadzi później do NullPointerException. I nie rozumiem za bardzo dlaczego metoda zwraca pustą zmienną green.

Dla mnie na przykład zaskakujące jest, że spodziewasz się, że ten wyjątek nie poleci ;-) Więc może będzie łatwiej wskazać gdzie się mylisz w swoim rozumowaniu, jeśli to rozumowanie wytłumaczysz.
Więc jak Ty to widzisz - dlaczego według Ciebie getGreen() który wywołujesz w Blue.metoda2() powinien zwrócić coś innego, niż null? Skąd Twoim zdaniem miałoby się wziąć coś w polu green w obiekcie blue?

Błąd w moim rozumowaniu tkwił chyba w tym, że uważałem zadeklarowaną zmienną green na samej górze jako coś w rodzaju zmiennej statycznej. Zakładałem również, że jeśli getGreen() w metoda1() zwraca adres obiektu green to tak samo powinno być gdy metodę getGreen() wywołuję z klasy Blue. Ale przyznam, że dobre pytanie mi zadałeś, powinienem sobie je częściej zadawać próbując coś rozwikłać.

Prosiłbym jeszcze o potwierdzenie czy teraz dobrze to rozumuję. W metodzie main mam zainicjalizowany obiekt o nazwie obj. Wywołuje on metodę metoda1() i zmienna green będzie obiektem tylko dla obiektu obj. Dlatego jeśli chcę się odnieść z zewnątrz do zmiennej green jako obiektu to mogę to zrobić poprzez obj.green. Inne sposoby będą zwracały null, ponieważ zmienna green nie będzie już obiektem poza obszarem obj (chyba, że skorzystam z metody setGreen(green), która mi ustawi tę zmienną dla konkretnego obiektu np. blue.setGreen(green)).

1
SlowSheep napisał(a):

Prosiłbym jeszcze o potwierdzenie czy teraz dobrze to rozumuję. W metodzie main mam zainicjalizowany obiekt o nazwie obj.

Zgadza się. Na początek z niezainicjowanymi zmiennymi green i blue (wskazującymi na null).

Wywołuje on metodę metoda1() i zmienna green będzie obiektem tylko dla obiektu obj.

I zmienna green będzie wskazywać na obiekt. Obiekt będzie istniał.

Dlatego jeśli chcę się odnieść z zewnątrz do zmiennej green jako obiektu to mogę to zrobić poprzez obj.green.

Skądkolwiek. Nie tylko z zewnątrz ale z obok i z wewnątrz. (Inna sprawa to w jaki sposób inni się o nim dowiedzą).

Inne sposoby będą zwracały null, ponieważ zmienna green nie będzie już obiektem poza obszarem obj ...

Będzie (wskazywać na obiekt). Ale to jest inna zmienna niż obj.blue.green i inna niż obj.green.green.

obj, obj.green i obj.blue są tak naprawdę zmiennymi które wskazują na różne obiekty klasy Green. Każda z nich jest inicjalizowana w innym miejscu. Każdy obiekt, na który wskazują, zawiera kolejne zmienne i te zmienne też trzeba inicjalizować.

0

Dzięki za objaśnienie Delor. Teraz już wszystko mi się poukładało.

1 użytkowników online, w tym zalogowanych: 0, gości: 1