Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem z dziedziczeniem
Forum PHP.pl > Forum > PHP
Bachus
Mam dwa obiekty. Jeden służy do inicjacji konfiguracji, obiektów pomocniczych, tworzenia instancji singletonów i innych drobnych rzeczy. Wszystkie obiekty w skrypcie dziedziczą z tego obiektu. Drugi obiekt dziedziczy z pierwszego i służy do wykonania konkretnego zadania.

Chciałem dodać (do pierwszego obiektu) wywoływaną zawsze z kontekstu drugiego obiektu prostą funkcję wyświetlającą print_r dla wszystkich zmiennych obiektu (żeby łatwiej było mi pisać i debugować). I tu napotkałem problem.

Jeśli funkcja jest zadeklarowana w obiekcie pierwszym, to mimo tego, że wywoływana jest z obiektu drugiego, $this odwołuje się do obiektu pierwszego.

Przygotowałem odrobinę kodu dla zilustrowania problemu (php5):

  1. <?php
  2. abstract class obj_1{
  3. public $zmienna_obj_1;
  4.  
  5. public function __construct(){
  6. $this->zmienna_obj_1 = &#092;"należę do obiektu 1\";
  7. }
  8.  
  9. public function debug(){
  10. echo &#092;"<pre>\";
  11. echo __CLASS__.&#092;"n\";
  12. foreach ($this as $nazwa => $zmienna) {
  13. echo $nazwa.&#092;": \";
  14. print_r($zmienna);
  15. echo &#092;"n\";
  16. }
  17. echo &#092;"</pre>\";
  18. }
  19. }
  20.  
  21. class obj_2 extends obj_1 {
  22.  
  23. private $zmienna_obj_2;
  24.  
  25. public function __construct(){
  26. parent::__construct();
  27. $this->zmienna_obj_2 = &#092;"należę do obiektu 2\";
  28. $this->debug();
  29. }
  30. }
  31.  
  32. $obj_2 = new obj_2();
  33. ?>


powyższy przykład generuje:

  1. <pre>
  2. obj_1
  3. zmienna_obj_1: należę do obiektu 1
  4. </pre>


Ponieważ w php nie ma czegoś takiego jak 'child' nie wiem co z tym zrobić. Ktoś ma jakiś pomysł jak to obejść?
nospor
jedna zmienna w klasie głównej. ją zmieniasz w klasach potomnych:

  1. <?php
  2.  
  3. abstract class obj_1{
  4. public $zmienna_obj;
  5.  
  6. public function __construct(){
  7. $this->zmienna_obj = &#092;"należę do obiektu 1\";
  8. }
  9.  
  10. public function debug(){
  11. echo &#092;"<pre>\";
  12. echo __CLASS__.&#092;"n\";
  13. foreach ($this as $nazwa => $zmienna) {
  14. echo $nazwa.&#092;": \";
  15. print_r($zmienna);
  16. echo &#092;"n\";
  17. }
  18. echo &#092;"</pre>\";
  19. }
  20. }
  21.  
  22. class obj_2 extends obj_1 {
  23.  
  24. public function __construct(){
  25. parent::__construct();
  26. $this->zmienna_obj = &#092;"należę do obiektu 2\";
  27. $this->debug();
  28. }
  29. }
  30.  
  31. ?>
Bachus
Nie o to chodzi. debug() powinno generować listę wszystkich zmiennych obiektu 2:

  1. <pre>
  2. obj_2
  3. zmienna_obj_1: należę do obiektu 1
  4. zmienna_obj_2: należę do obiektu 2
  5. </pre>


$zmienna_obj_1 odziedziczona została po obiekcie 1, $zmienna_obj_2 jest jej prywatną zmienną. Gdyby $zmienna_obj_2 była publiczna, funkcja działałaby prawie poprawnie, ale nie mogę i nie chcę zmieniać struktury obiektów po to żeby działała funkcja która tylko uprzyjemnia życie :-)
nospor
to w takim razie dodaj parametr fo funkcji debug, który będzie obiektem i w funkcji lub iterację po tym obiekcie. A wywoływać będziesz
  1. <?php
  2.  
  3. $this->debug($this);
  4.  
  5. ?>


edit: aczkolwiek pewnie też to nie zda egzaminu skoro zmienna jest prywatna.
dorób funkcję debug do drugiej klasy biggrin.gif
Bachus
Dokładnie :-) Już wcześniej próbowałem.

Dodać debug() do drugiej klasy mógłbym i wtedy działałoby, ale nie chcę powtarzać tej samej funkcji w 30 klasach. Właśnie do tego ma służyć dziedziczenie tongue.gif
nospor
w inncyh językach jest odatkowo protected (zminna prywatna ale dziedziczona). A php5? Spróbuj zamiast private dać protected
Bachus
Protected jest, ale działa tylko w jedną stronę - tzn zmienne obj1 są widoczne dla obj2, ale zmienne obj2 nie są widoczne dla obj1. Poza tym - o to właśnie chodzi żeby nie zmieniać widoczności zmiennych. Mam dobre powody żeby część zmiennych była prywatna.

Problem można uogólnić. Deklaracja

  1. <?php
  2.  
  3. abstract class obj_1{
  4. public $zmienna_obj_1;
  5.  
  6. public function __construct(){
  7. $this->zmienna_obj_1 = &#092;"należę do obiektu 1\";
  8. }
  9.  
  10. public function debug(){
  11. echo &#092;"<pre>\";
  12. echo __CLASS__.&#092;"n\";
  13. foreach ($this as $nazwa => $zmienna) {
  14. echo $nazwa.&#092;": \";
  15. print_r($zmienna);
  16. echo &#092;"n\";
  17. }
  18. echo &#092;"</pre>\";
  19. }
  20. }
  21.  
  22. class obj_2 extends obj_1 {
  23.  
  24. private $zmienna_obj_2;
  25.  
  26. public function __construct(){
  27. parent::__construct();
  28. $this->zmienna_obj_2 = &#092;"należę do obiektu 2\";
  29. $this->debug();
  30. }
  31. }
  32.  
  33. ?>

to z jakiegoś powodu nie to samo co
  1. <?php
  2.  
  3. class obj_2 {
  4.  
  5. public $zmienna_obj_1;
  6. private $zmienna_obj_2;
  7.  
  8. public function __construct(){
  9. parent::__construct();
  10. $this->zmienna_obj_1 = &#092;"należę do obiektu 1\";
  11. $this->zmienna_obj_2 = &#092;"należę do obiektu 2\";
  12. $this->debug();
  13. }
  14.  
  15. public function debug(){
  16. echo &#092;"<pre>\";
  17. echo __CLASS__.&#092;"n\";
  18. foreach ($this as $nazwa => $zmienna) {
  19. echo $nazwa.&#092;": \";
  20. print_r($zmienna);
  21. echo &#092;"n\";
  22. }
  23. echo &#092;"</pre>\";
  24. }
  25. }
  26.  
  27. ?>


Dlaczego?

Gdyby był sposób żeby odwołać się do obiektu-dziecka nie wiedząc jaka to klasa, problem znikłby.
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.