Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dziedziczenie i zmienne statyczne
Forum PHP.pl > Forum > PHP > Object-oriented programming
peter13135
Mój "problem" dotyczy programowania obiektowego. W moim przypadku chodzi o javę, ale myślę, że to dotyczy ogólnie programowania obiektowego.
Dajmy na to, mam klasę abstrakcyjną typu wielokąt:

  1. abstract class wielokąt{
  2. private int liczbaKątów;
  3.  
  4. public int getLiczbaKątów() {return liczbaKątów; }
  5. public int setLiczbaKątów(int lk) { liczbaKątów = lk; }
  6. }


Następnie robię sobie klasę trójkąt:
  1. class trójkąt extend wielokąt{
  2.  
  3. trójkąt()//w php będzie to __construct()
  4. {
  5. setLiczbaKątów(3);
  6. }
  7.  
  8. }
  9.  


W analogiczny sposób robię sobie klasy czworokąt, pięciokąt itd.

Następnie w kodzie mam wiele instancji tych klas (trójkątów, czworokątów itd.)
Okazuje się, że mój kod jest nieco pamięciożerny, bo liczba kątów dla klasy trójkąt zawsze będzie równa 3, a ja tworzę dla każdej instancji klasy osobną zmienną.

Niby z pomocą przychodzą zmienne statyczne, ale jeśli takową zadeklaruję w klasie wielokąt, to liczba kątów dla trójkąta i czworokąta będzie taka sama.
Muszę więc zadeklarować tą zmienną statyczna w klasach potomnych, czyli w trójkącie, czworokącie,...,n-kącie. Ale wtedy moje metody zdefiniowane w klasie wielokąt nie będą działały, bo przecież w klasie wielokąt nie ma zmiennej o nazwie liczbaKątów.
Ratunkiem jest stworzenie tych metod w klasach potomnych, a w klasie nadrzędnej zostawić tylko "abstrakcyjne nagłówki".
Jednak... nie bardzo mi to pasuje, bo każda z tych metod (setter i getter) bedzie wyglądał tak samo. Nie chcę więc powielać kodu.

jak temu zaradzić ?
Crozin
1. Na prawdę ta jedna zmienna jest przyczyną problemów z pamięcią?
2.
  1. abstract class Wielokąt {
  2. abstract public int getLiczbaKątów();
  3. }
  4.  
  5. public class Trójkąt extends Wielokąt {
  6. public int getLiczbaKątów() {
  7. return 3;
  8. }
  9. }
  10.  
  11. public class Prostokąt extends Wielokąt {
  12. public int getLiczbaKątów() {
  13. return 4;
  14. }
  15. }
3. Uprzedzając pytanie - tak, JIT "zinlineuje" wywołanie metody getLiczbaKątów().
4. Korzystanie ze static prawie nigdy nie jest dobrym pomysłem na rozwiązanie problemów.
peter13135
Cytat
1. Na prawdę ta jedna zmienna jest przyczyną problemów z pamięcią?

Nie, ta zmienna, trójkąty i czworokąty to tylko taki przykład, aby było przejrzyściej. W rzeczywistości mam kilkanaście takich zmiennych. Jedne maja typy proste. większość to dość rozbudowane obiekty, kilka z nich to pliki graficzne ładowane z dysku. Prawdopodobnie gdybym to wszystko ładował dla każdej instancji oddzielnie, to i tak współczesnemu komputerowi to wielkich problemów nie zrobi, ale mimo to, chcę to zrobić tak jak należy.
2. No fajnie, ale w każdej z tych klas potomnych robisz metodę. Tak to i ja potrafię, ale jak pisałem - chcę tego uniknąć.

Dam nieco bardziej bardziej rozbudowany i obrazowy przykład (bez kodu).
Dajmy na to, że mamy grę, w której są różne jednostki (powiedzmy smerfy i gargamele). Mamy więc klasę Jednostka, która posiada wiele "właściwości", np. szybkość, wytrzymałość, pozycja na mapie, rodzaje broni, siła uderzenia, odporność na jakieś tam ataki i mnóstwo innych. Wszelkie "akcje" czyli na przykład ruch, albo zmniejszenie punktów wytrzymałości jednostki ma robić klasa "Jednostka", czyli ta nadrzędna.

Klasy potomne jak Smerf czy Gargamel (które dziedziczą po klasie Jednostka) mają takie same "zachowania" (np. metoda ruch() będzie zwiększała pozycję o wartość szybkość) tylko na innych danych. Np. Smerf będzie miał szybkość = 2, a Gargamel szybkość = 1.

Trochę nie widzi mi się pisanie dla każdej potomnej klasy metod typu getJakasWłaściwość() {return new JakisObiekt(1,2,3,4,5,2,4,'abc')}.

Mam rozumieć, że jeśli zrobię metodę typu

getSmerfImage() {return Image("./obrazki/obrazeksmerfa.jpg")} - to w pamięci będe miał tylko jeden załadowany obraz bez względu czy będę miał 3 czy 8 smerfów ?


Aha... i czemu static "nie rozwiązuje problemów" ?
Crozin
Jeżeli możesz podaj proszę dokładny opis swojego przypadku, ponieważ w przykładach jakie podajesz każdy obiekt powinien mieć swoją lokalną kopię danych, bądź powinien istnieć inny obiekt zwracający prędkość/ilość kątów na podstawie przekazanego mu obiektu: (raczej gorsze rozwiązanie)
  1. public int getIlośćKątów(Wielokąt wielokąt) {
  2. if (wielokąt instanceof Prosotkąt) {
  3. return 4;
  4. } else if (wielokąt instanceof Trójkąt) {
  5. return 3;
  6. }
  7.  
  8. throw new IllegalArgumentException("...");
  9. }
Cytat
Mam rozumieć, że jeśli zrobię metodę typu

getSmerfImage() {return Image("./obrazki/obrazeksmerfa.jpg")} - to w pamięci będe miał tylko jeden załadowany obraz bez względu czy będę miał 3 czy 8 smerfów ?
Nie, będziesz miał po jednym załadowanym obrazie na obiekt (bardzo złe rozwiązanie). Ale takim czymś nie powinien zajmować się już Twój obiekt Jednostka - za dużo zadań mu przydzielasz: reprezentowanie obiektu na mapie (pozycja, ruch), obiekt domeny (Smerf/Gargamel) i do tego chciałbyś jeszcze dorzucić śmieci związane z renderowaniem grafiki? Single responsibility principle.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.