Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Nadpisywanie składnika i sterowanie dostępem w klasie dziedziczącej
Forum PHP.pl > Forum > PHP > Object-oriented programming
amii
Przykład skopiowany z manula, więc myślę że źródło najbardziej wiarygodne jakie może być:
http://www.php.net/manual/pl/language.oop5.visibility.php
Jednej rzeczy nie rozumiem dlaczego w klasie MyClass2 nie można się odwołać do echo $obj2->protected; skoro wcześniej zasłania ona zmienną z klasy podstawowej zresztą jeśli jest protected to nawet gdyby nie było zasłonięcia powinniśmy się móc odwołać do składnika protected z klasy podstawowej

  1. <?php
  2. /**
  3.  * Define MyClass
  4.  */
  5. class MyClass
  6. {
  7. public $public = 'Public';
  8. protected $protected = 'Protected';
  9. private $private = 'Private';
  10.  
  11. function printHello()
  12. {
  13. echo $this->public;
  14. echo $this->protected;
  15. echo $this->private;
  16. }
  17. }
  18.  
  19. $obj = new MyClass();
  20. echo $obj->public; // Works
  21. echo $obj->protected; // Fatal Error OK odwołanie z zewnątrz do składnika chronionego
  22. echo $obj->private; // Fatal Error OK odwołanie z zewnątrz do składnika prywatnego
  23. $obj->printHello(); // Shows Public, Protected and Private OK wywołanie funkcji publicznej z zewnątrz (funkcja może grzebać w prywatnych składnikach swojej klasy)
  24.  
  25.  
  26. /**
  27.  * Define MyClass2
  28.  */
  29. class MyClass2 extends MyClass
  30. {
  31. // We can redeclare the public and protected method, but not private
  32. protected $protected = 'Protected2'; //zasłania zmienną z klasy podstawowej questionmark.gif?
  33.  
  34. function printHello()
  35. {
  36. echo $this->public;
  37. echo $this->protected;
  38. echo $this->private;
  39. }
  40. }
  41.  
  42. $obj2 = new MyClass2();
  43. echo $obj2->public; // Works
  44. echo $obj2->private; // Undefined OK bo składnik prywatny
  45. echo $obj2->protected; // Fatal Error questionmark.gif? dlaczego nie wywołuje składnika ze swojej klasy, który powinien zasłonić składnik z klasy podstawowej
  46. $obj2->printHello(); // Shows Public, Protected2, Undefined //OK wywołanie funkcji, która zasłania tą z klasy podstawowej mimo, że jest to funkcja z klasy MyClass2 wyświetla odziedziczony składnik public z klasy MyClass i zasłaniający składnik protected z klasy MyClass2 składnik private jest niedostępny.
  47.  
  48. ?>
Zyx
Dlatego, że odwołujesz się do niego w kodzie, który nie znajduje się ani w klasie MyClass, ani MyClass2.
amii
I wszystko jasne smile.gif dopiero zaczynam się uczyć obiektówki i takie rzeczy męczą a dla starych wyjadaczy to zapewne pestka.

Poprawna wersja:
  1. class MyClass2 extends MyClass
  2.  
  3. {
  4.  
  5. // We can redeclare the public and protected method, but not private
  6.  
  7. protected $protected = 'Protected2'; //zasłania zmienną z klasy podstawowej
  8.  
  9.  
  10. function printHello()
  11.  
  12. {
  13.  
  14. echo $this->public;
  15. echo $this->protected;
  16. echo $this->private;
  17.  
  18. }
  19.  
  20.  
  21. echo $this->protected; //tu już można i wyświetli Protected2
  22. echo self::protected; //tak samo jak wyżej ?
  23. echo MyClass::protected; //można też tak operatorem zakresu sięgnąć do zasłoniętego składnika z klasy podstawowej i wyświetli Protected
  24. echo parent::protected; //tak samo jak wyżej ?
  25.  
  26. }


Crozin
Jak rozumiem ten kod, który opatrzyłeś komentarzami jest umieszczony wewnątrz jakiejś metody, tak?

Operator paamayim nekudotayim (genialna nazwa swoją drogą) używany jest przy odwołaniach statycznych. Wyjątkiem jest jedynie tutaj konstrukcja "parent::xxx" (deweloperzy PHP popisali się tutaj inteligencją...). Właściwości dynamicznych nie możesz używać jak statycznych (self::, MyCLass::$protected) - musiałbyś zadeklarować je jako statyczne (wtedy zaś nie mógłbyś się do nich odwoływać jak do dynamicznych).
amii
Teraz te odwołania są w metodzie printHello()
1. Czyli jak rozumiem mamy tu dwa rodzaje dostępu dla składników statycznych (które mogą być zasłonięte lub nie) i do składników dynamicznych (które mogą być zasłonięte lub nie) tak jak we wzorcu poniżej.


  1. class MyClass2 extends MyClass
  2.  
  3. {
  4.  
  5. // We can redeclare the public and protected method, but not private
  6.  
  7. protected $protected = 'Protected2'; //zasłania zmienną z klasy podstawowej
  8.  
  9.  
  10. function printHello()
  11.  
  12. {
  13.  
  14. echo 'Zmienna chroniona klasy ' .__CLASS__. ' ma wartość: '.$this->protected . '<br>'; //tu już można i wyświetli Protected2
  15. //echo self::protected; niepoprawne bo używany do odwołań statycznych poprawny byłby gdyby zmienna protected była static
  16. //echo MyClass::protected; niepoprawne bo używany do odwołań statycznych poprawny byłby gdyby zmienna protected była static
  17. echo 'Zmienna chroniona zasłonięta dla klasy podstawowej dla ' .get_class($this). ' ma wartość: '. parent::protected . '<br>'; //czyli tak sięgamy do zasłoniętych składników z klasy podstawowej nie mających przydomka static ?
  18.  
  19. }
  20.  
  21.  
  22. }
  23.  
  24. //jesteśmy o obszarze globalnym poza klasą
  25. $MyClass = new MyClass1(); //tworzymy instancję obiektu klasy podstawowej
  26. $MyClass2 = new MyClass2(); //tworzymy instancję obiektu klasy pochodnej
  27.  
  28. //$MyClass->printHello(); //to jest jasne
  29. $MyClass2->printHello();
  30. /* OUTPUT
  31. Zmienna chroniona klasy MyClass2 ma wartość: Protected2
  32. Zmienna chroniona zasłonięta dla klasy podstawowej dla MyClass2 ma wartość: Protected
  33. */
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.