Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][OOP] Metoda __set nie działa?
djgarsi
post 30.04.2013, 17:22:30
Post #1





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

Ostrzeżenie: (0%)
-----


Witam serdecznie.
Rozpocząłem naukę PHP OOP i jak to zwykle bywa, napotkałem problem i nie wiem o co chodzi.
Otóż mam klasą:
  1. <?php
  2.  
  3. class Samochod {
  4. public $predkosc_maksymalna;
  5.  
  6. function __set($nazwa, $wartosc) {
  7. if (($nazwa == "predkosc_maksymalna") && ($wartosc > 0) && ($wartosc < 350)) {
  8. $this->predkosc_maksymalna = $wartosc;
  9. }
  10. else {
  11. echo "Za szybko, zwolnij!";
  12. }
  13. }
  14. }
  15.  
  16. $pojazd = new Samochod;
  17. $pojazd->$predkosc_maksymalna = 200;
  18.  
  19. echo $pojazd->predkosc_maksymalna;
  20. ?>


Przy każdej wartości (np. 200) wyrzuca, że "za szybko" a jak wiadomo przy 200 powinno działać normalnie.
Proszę o pomoc.


--------------------
Go to the top of the page
+Quote Post
viking
post 30.04.2013, 17:52:01
Post #2





Grupa: Zarejestrowani
Postów: 6 366
Pomógł: 1115
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


  1. $pojazd->predkosc_maksymalna = 200; //bez $


Poza tym dodaj tam sobie w ifie echo 'wykonałem';, poczytaj dokumentację http://www.php.net/manual/en/language.oop5....php#object.set zwłaszcza
Cytat
/** Overloading not used on declared properties. */
public $declared = 1;
i zastanów się dlaczego to jest źle.

Ten post edytował viking 30.04.2013, 17:57:44


--------------------
Go to the top of the page
+Quote Post
djgarsi
post 30.04.2013, 18:06:15
Post #3





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

Ostrzeżenie: (0%)
-----


Cytat(viking @ 30.04.2013, 18:52:01 ) *
  1. $pojazd->predkosc_maksymalna = 200; //bez $


Poza tym dodaj tam sobie w ifie echo 'wykonałem';, poczytaj dokumentację http://www.php.net/manual/en/language.oop5....php#object.set zwłaszcza
i zastanów się dlaczego to jest źle.



No dobra, usunąłem $, dodałem echo w if'ie i ustawiłem public $predkosc_maksymalna=0;.
Sytuacja wygląda teraz tak, że wyświetla po prostu wartość prędkości, tak jakby pomijało całkiem if'a.


--------------------
Go to the top of the page
+Quote Post
mortus
post 30.04.2013, 18:31:12
Post #4





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


Przeciążone metody magiczne nie operują na właściwościach publicznych, bo te z założenia są dostępne za pomocą operatora wyłuskania ->. Dlatego metoda __set() nie jest w ogóle u Ciebie uruchamiana.

Pisałem już o tym szerzej na tym forum.

No i oczywiście największy sens ma przechowywanie danych, do których chcemy mieć dostęp za pomocą operatora wyłuskania (i przeciążonych metod __set() i __get()) w prywatnej tablicy.

Ten post edytował mortus 30.04.2013, 18:51:28
Go to the top of the page
+Quote Post
djgarsi
post 30.04.2013, 21:09:41
Post #5





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

Ostrzeżenie: (0%)
-----


Kurcze, takie niuanse podczas nauki OOP.

@mortus: mógłbyś bardziej łopatologicznie napisać o co chodzi z tymi metodami __set i __get?


--------------------
Go to the top of the page
+Quote Post
CuteOne
post 30.04.2013, 21:55:44
Post #6





Grupa: Zarejestrowani
Postów: 2 958
Pomógł: 574
Dołączył: 23.09.2008
Skąd: wiesz, że tu jestem?

Ostrzeżenie: (0%)
-----


  1. class Registry {
  2.  
  3. private $_data = array();
  4.  
  5. public function __set($key, $value) {
  6.  
  7. $this->_set($key, $value);
  8. return $this;
  9. }
  10.  
  11. private function _set($key, $value) {
  12.  
  13. $this->_data[$key] = $value;
  14. }
  15.  
  16. public function __get($key) {
  17. if(isset($this->_data[$key]) {
  18. return $this->_data[$key]; //lub $this->_get($key);
  19. }
  20. }
  21. ....


Metody _set i _get mogą być publiczne,chronione lub jak w powyższym przykładzie prywatne. Cały trick polega na tym, że dane przechowujesz w tablicy (możesz np. zabezpieczyć je przed nadpisaniem)
Go to the top of the page
+Quote Post
mortus
post 1.05.2013, 08:59:25
Post #7





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


@CuteOne: Metody magiczne powinny być publiczne, bo oczekujemy publicznego/globalnego dostępu do nich. Niemniej metody zadeklarowane jako prywatne również działają, co jest karygodnym błędem twórców PHP (zdaje się że w wersji 5.3 PHP pojawiał się w tej sytuacji WARNING).

Jednak nie o to mi chodziło we wcześniejszej odpowiedzi. Łopatologicznie:
przykład, w którym nie korzystamy z metod __set() i __get()
  1. class A {
  2. public $a;
  3. public function __set($key, $value) {
  4. $this->$key = $value;
  5. }
  6. public function __get($key) {
  7. return $this->$key;
  8. }
  9. }
  10. $o = new A;
  11. $o->a = 10;
  12. echo $o->a;

Ponieważ właściwość $a klasy A jest właściwością publiczną, mamy do niej bezpośredni dostęp za pomocą operatora wyłuskania -> i magiczne metody __set() i __get() nie będą w tej sytuacji wywoływane.

przykład, w którym korzystamy z metod __set() i __get()
  1. class A {
  2. private $a;
  3. public function __set($key, $value) {
  4. $this->$key = $value;
  5. }
  6. public function __get($key) {
  7. return $this->$key;
  8. }
  9. }
  10. $o = new A;
  11. $o->a = 10;
  12. echo $o->a;

Ponieważ właściwość $a klasy A jest właściwością prywatną, nie mamy do niej bezpośredniego dostępu za pomocą operatora wyłuskania -> i tutaj potrzebujemy magicznych metod __set() i __get() - tutaj będą one wywoływane.

Niemniej wykorzystanie tych metod magiczny w ten sposób jest bez sensu, bo musielibyśmy dokładnie kontrolować wszystkie właściwości klasy. Rozwiązanie, które podał CuteOne ma zdecydowanie większy sens.

Ten post edytował mortus 1.05.2013, 09:03:39
Go to the top of the page
+Quote Post
djgarsi
post 1.05.2013, 11:17:42
Post #8





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

Ostrzeżenie: (0%)
-----


Super. Chyba rozumiem. Mój kod będzie teraz poprawny?
  1. class Samochod {
  2. private $predkosc_maksymalna;
  3.  
  4. function __set($nazwa, $wartosc) {
  5. if (($nazwa == "predkosc_maksymalna") && ($wartosc > 0) && ($wartosc < 350)) {
  6. $this->predkosc_maksymalna = $wartosc;
  7. echo "Predkosc ok.";
  8. }
  9. else {
  10. echo "Za szybko, zwolnij!";
  11. }
  12. }
  13. public function __get($wartosc) {
  14. return $this->predkosc_maksymalna;
  15. }
  16. }
  17.  
  18. $pojazd = new Samochod;
  19. $pojazd->predkosc_maksymalna = 200;
  20.  
  21. echo $pojazd->predkosc_maksymalna;


--------------------
Go to the top of the page
+Quote Post
mortus
post 1.05.2013, 11:44:46
Post #9





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


Przede wszystkim takie użycie metod __set() i __get() nie ma praktycznego zastosowania, bo zmusza programistę do kontrolowania wszystkich właściwości klasy (trzeba znać dokładnie nazwy tych właściwości). Lepiej użyć, jak już zwracaliśmy uwagę, tablicy:
  1. class Car {
  2. private $features = array();
  3. public function __set($key, $value) {
  4. $this->features[$key] = $value;
  5. }
  6. public function __get($key) {
  7. return $this->features[$key];
  8. }
  9. }
  10. $car = new Car;
  11. $car->max_speed = 200;
  12. var_dump($car);

Poza tym źle napisałeś metodę __get(), gdybyś miał np. pole prywatne kolor i próbował pobrać wartość tego pola za pomocą $pojazd->kolor, to nadal otrzymasz wartość prędkości maksymalnej.

No i w końcu to co stricte dotyczy OOP, settery i gettery (również te magiczne) nie są dobrym miejscem do kontrolowania wartości zmiennych. Powinna do tego raczej służyć osobna metoda np. sprawdzPredkosc().

I jeszcze jedno... takie przeciążone metody __set() i __get() raczej nie nadają się do powszechnego użytku (w ogóle nie pasują do klasy Samochod). Zdecydowanie lepszy przykład podał CuteOne - klasa Rejestr, która ma za zadanie przechowywać dowolne lecz istotne dane dla naszej aplikacji. W klasie Samochod lepiej będzie wykorzystać po prostu setPredkoscMaksymalna() i getPredkoscMaksymalna().
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 23.05.2024 - 05:46