Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Obiekty a zmienne
Forum PHP.pl > Forum > PHP > Object-oriented programming
slash12345
Witam,
Mam taką klasę w php:
  1. <?php
  2. class test{
  3. public $a = 0;
  4. public $b = $a;
  5. }
  6. ?>

Przy próbie uruchomienia, skrypt zgłasza błąd. Jak więc mogę przypisać wartość jednej zmiennej do drugiej?
Czyżby twórcy php zapomnieli o tym drobnym szczególe?
mike
W żadnym języku tak nie można.
I bardzo dobrze. Bo niby jak stworzysz taki obiekt? A co jak zapomnisz ndać wartosć dla test::$a?
Pola klasy mogę mieć domyślnie tylko przypisanie wartości.

Możesz to zrobić tak:
  1. <?php
  2.  
  3. class test {
  4. public $a = 0;
  5. public $b;
  6.  
  7. public function __construct()
  8. {
  9. $this->b = $this->a;
  10. }
  11. }
  12.  
  13. ?>
bigZbig
Moim skromnym zdaniem definiowanie wartosci wlasciwosci poza metodami powinno byc dopuszczalne jedynie dla wlasciwosci statycznych. W przypadku wlasciwosci niestatycznych, poza metodami powinno sie je tylko deklarowac, natomiast konkretne wartosci powinno sie im nadawac w konstruktorze lub innej metodzie.
Cysiaczek
A co, jeśli będę chciał mieć tak:
  1. <?php
  2. class cysio{
  3.  
  4. public $path='/ble/ble/ble/';
  5.  
  6. public function __construct(){
  7. $data=file_get_conte ... //bierzemy coś z pliku
  8. $this->path='/ble/ble/ble/kolejne/ble/';
  9.  
  10. }
  11.  
  12. }
  13. ?>



Może niezbyt uzyteczny przykład smile.gif , ale w zasadzie jest uzasadnione przypisanie wartości przy deklaracji czy nie?
bigZbig
@Cysiaczek, ale po co skoro zmienne nie istnieja dopuki nie utworzysz obiektu, a jak tworzysz obiekt to pierwsze co robisz to ustawiasz wartosc zadeklarowanej wlasciwosci?

  1. <?php
  2. class cysio{
  3. public $path;
  4.  
  5. public function __construct(){
  6. $this->path = '/ble/ble/ble/';
  7. $data=file_get_conte ... //bierzemy coś z pliku
  8. $this->path = '/ble/ble/ble/kolejne/ble/';
  9. }
  10. }
  11. ?>
Cysiaczek
Tutaj się zgadzamy. Tak można zrobić i nawet jest to lepiej widziane. Zastanawia mnie jednak, co się staie, jeśli usuniemy z klasy konstruktor? Takie klasy zdarzają sie dość często. Albo mam jeszcze inny przykład:
Co zrobisz z implementacją klasy abstrakcyjnej, gdzie np. w abstrakcyjnej ustalasz sobie jakąś wartość dla składowej?
Ehh. Ten upiorny relatywizm :| Nic stałego sad.gif
bigZbig
1. Dlaczego mialbym usuwac konstruktor z klasy skoro juz w niej jest?
2. Czy w klasie abstrakcyjnej nie mozna stworzyc konstruktora?
Cysiaczek
Ad1. Chodzi o klasy, w których nie deklarujesz konstruktora
Ad2. Trzeba wywołać go ręcznie z pochodnej (i to najlepiej w konstruktorze [patrz wyżej]) biggrin.gif
mike
Cytat(Cysiaczek @ 11.07.2006, 09:18 ) *
Ad1. Chodzi o klasy, w których nie deklarujesz konstruktora
No ale to kiepski przykład.
Konstruktor zawsze powinno się pisać, więc po co wspominasz o klasach bez niego?

Nie twierdze jednak, że nie powinno się ustawiać wartości dla pól, tutaj akurat nie podzielam zdania ~bigZbiga
Cysiaczek
OOpsssaaa. Pomyłka biggrin.gif blink.gif ohmy.gif

Jak się nie zdefiniuje konstruktora w pochodnej, to z bazowej jest przecież wywoływany automatycznie. biggrin.gif
Dalej jednak jest problem ze składowymi, które trzeba jakoś zainicjować na poczatku, a nie mozna zrobić tego w klasie bazowej w konstruktorze, a nie ma konstruktora w pochodnej. blinksmiley.gif

Aha. W jakimś topiku pisałem na temat prywatnego konstruktora. Już mam kontekst biggrin.gif
Napiszę tutaj, bo częsciowo temat pasuje.
  1. <?php
  2. abstract class CoolPeople{
  3.  
  4. private function __construct(){
  5. print 'jestem bazowy';
  6. }
  7.  
  8. abstract function beCool();
  9. }
  10.  
  11. class cysio extends CoolPeople{
  12.  
  13. public function __construct(){
  14. parent::__construct();
  15. }
  16.  
  17. function beCool(){}
  18. }
  19.  
  20. $ob=new cysio;
  21. ?>


...A teraz usuńcie cały konstruktor z klasy pochodnej i juz error gotowy :|
Ludvik
Udało Ci się wywołać prywatny konstruktor z konstruktora klasy pochodnej? Jeżeli testowałeś ten kod, to wypadało by raczej zgłosić to jako błąd do ekipy od php. A tak na marginesie, przy usunięciu konstruktora z klasy pochodnej powinien chyba zostać utworzony automatycznie pusty? Czy może się mylę?

Poza tym normalni programiści nie robią takich rzeczy. Myślisz o sytuacjach, które nigdy nie będą miały miejsca przy pisaniu kodu przez cywilizowanych ludzi.

Ja zwykle poza konstruktorem nadaję atrybutom wartości takie jak pusta tablica czy ciąg znaków. Tak czy inaczej, w konstruktorze je nadpisuję, jeżeli jest taka potrzeba.
Cysiaczek
Mam taka książkę "PHP5 Obiekty, wzorce, narzędzia" . Nie będę cytował, ale:
Jest napisane, że jeśli w klasie pochodnej deklarujesz konstruktor, to musisz wziąść odpowiedzialność za ręczne wywołanie konstruktora klasy bazowej, bo inaczej możesz otrzymać nie dokońca skonstruowany obiekt (jeśli istnieje i właśnie przez parent::__construct(wsio co trzeba tu)).

Jeśli nie dasz konstruktora w klasie pochoden, to jest automatycznie wywoływany konstruktor klasy bazowej jako GŁÓWNY. Teraz zonk jest właśnie z tą widzialnością, ale to każdy może sobie sam zobaczyć uruchamiając powyższy przykład.

Jeśłi chodzi o moje ucywilizowanie... tongue.gif to chyba nigdy nie nastapi guitar.gif
Ludvik
No jasne, działanie konstruktorów znam, ale nie w tym rzecz. Zwróciłem uwagę na to, że wywołujesz z klasy pochodnej konstruktor klasy bazowej, który został zadeklarowany jako prywatny, czyli nie jest widzialny przez klasę dziedziczącą. Gdyby był chroniony, to inna sprawa...
Cysiaczek
Też mnie to zdziwiło, ale to niekoniecznie jest bład php, bo w końcu wywołujesz przez '::', a więc może idzie jako statyczne wywołanie? Znalazłem podobnego buga dot. wywołania dziedziczącego Singletona na php.net . Ponoć naprawili.:| Właściwie to mi taki "bug" nie przeszkadza smile.gif. Zresztą... nie znam się aż tak dobrze.
Jak ktoś ma pomysł co zrobic z tym fantem, to niech napisze smile.gif
Ludvik
Konstruktor nie może być wywołany statycznie. Sama jego natura wymaga obiektu, żeby móc przy nim operować. Taka składnia to pomysł twórców języka. W javie jest referencja do przodka...

Błędy raczej powinny przeszkadzać tongue.gif Ten akurat pozwala na ominięcie jednej z ważniejszych rzeczy w oop. Wystarczy zmienić modyfikator na protected i po sprawie. A jeżeli wtedy usuniemy konstruktor z pochodnej, to juz nasz problem smile.gif
Cysiaczek
No własnie nie. protected jest ok - widac go w pochodnych zawsze. Mnie zastanawia, czy własnie uzycie
parent::__construct();
nie jest tutaj kluczowe i dozwolone ze względu na konieczność skonstruowania obiektu - tzn jest konstruktor klasy pochodnej, więc obiekt musi sie pojawić. To, że jest konstruktor w bazowej i jest wykonany jest implikowane przez publiczny konstruktor pochodnej.
ehh.
1. sprawdze jeszcze dla zwykłego dziedziczenia. <--sprawdzone - działa
2. wywołanie w pochodnej przez parent::__construct w publicznej metodzie innej niż konstruktor wywołuje spodziewany bład.
Ludvik
W tym wypadku nie ma prawa wystąpić jakiegolwiek odstępstwo od reguły. Prywatny znaczy prywatny, a nie chroniony - zawsze. Kontruktory trzeba tworzyć z głową. Przecież prywatny konstruktor, inicjujący zmienne publiczne/chronione danej klasy jest całkowicie bez sensu... Chroniony może już się tym zająć, bo nie zostawi syfu w zmiennych.
Cysiaczek
W zasadzie, to jak robisz konstruktor w klasie bazowej, to chyba chcesz, żeby został wywołany? Może właśnie to konstruktor klasy bazowej musi być zawsze publiczny, żeby prawidłowo zainicjowac obiekt, bo co Ci po kawałku obiektu? Poczytam na php.net w bug rapartach i zobaczę, czy cos tam mają wiecej na ten temat. Do manuala to mozna teraz mieć pretensje, bo bardzo po macoszemu traktuje konstruktory :|
bigZbig
Uwazam ze wlasciwosci predefiniowane niestatyczne nie powinno sie ustawiac poza konstruktorem bo:

Istnieja tylko kiedy istnieje obiekt, a obiekt jest tworzony przez konstruktor zatem konstruktor powinien im nadawac te wartosci nawet jesli wszystkie instancje tej samej klasy maja miec poczatkowo te sama wartosc tej samej wlasciwosci. Jest to moim zdaniem logiczne i intuicyjne.

W Action Scripcie np. przypisanie wartosci do wlasciwosci przy jej inicjalizacji automatycznie traktowane jest jak wlasciwosci statyczne. Oczywiscie mowie tu o pisaniu klas, a nie prototypow.
Ludvik
Konstruktor nie musi być publiczny. Prywatne konstruktory przydają się przy implementacji wzorca singleton. Co mi po kawałku obiektu? Hmmm... a co mi po kimś, kto tak pisze klasy, że nie inicjuje wszystkich zmiennych? Przy programowaniu trzeba myśleć, tak jak przy wielu innych rzeczach. Żaden język nie jest odporny na niedouczonych programistów smile.gif
Cysiaczek
@bigZbig - W php konstruktor nie musi byc zadeklarowany, aby powstal obiekt. Jest raczej traktowany jako funkcja uruchamiana po to, aby wlasnie ustawic pewne wspólne dla wszystkich obiektów cechy i takież operacje. Nie wiem, czy rdzeń języka jest tak skonstruowany, że interpreter sam sobie dopisuje konstruktor, ale raczej tak nie jest. Jak go nie ma, to nie ma i tyle.
bigZbig
To ze nie musisz jawnie zadeklarowac konstruktora nie znaczy, ze go nie ma. Jesli nie ustalasz wartosci poczatkowych dla wlasciwosci obiektu to nie musisz pisac konstruktora, ale jak takie sa to powinienes to zrobic wlasnie w konstruktorze. Podobnie jest z destruktorem, ktorego piszesz tylko jesli chcesz wykonac jakies nietypowe operacje (np. zapisac cos w bazie danych) zaraz przed zdekonstruowaniem obiektu.
Cysiaczek
Cóż. Zwykle robię tak jak mówisz, ale jeśli chcę "dowartościować" tylko jedną składową, z która obiekt zawsze startuje, a cała reszta jest wypełniana potem w innych metodach, to chyba szkoda czasu i tych paru linijek kodu na konstruktor, prawda?
Ludvik
A co to za różnica w czasie wykonania? Przecież jakoś te wartości trzeba przypisać, niezależnie od tego czy statycznie w klasie czy w konstruktorze. Nigdy podczas profilowania nie myślałem o takich optymalizacjach...

Nie szkoda kilku linijek... Zawsze można zapisać konstruktor (a nawet klasę) w jednej smile.gif

Jeżeli nie potrzebujesz zmiennych to ich nie inicjuj. Jeżeli może zajść potrzeba ich użycia, wtedy musisz się upewnić, że będą miały prawidłową zawartość. W jaki sposób to zrobisz, to już twoja sprawa.
bigZbig
Słuchaj @Cysiaczek php to bardzo elastyczny jezyk. Mozesz w nim zrobic wiele rzeczy na wiele roznych sposobow, wiele tez mozesz nie robic choc teoretycznie powinienes. To co robisz zalezy od Ciebie. Ja też robie sporo odstepstw od tak zwanych zalecen programistycznych, ale zawsze staram sie byc tego swiadom. Jesli Ci szkoda czasu na pisanie konstruktora to go nie pisz.
Cysiaczek
Ale się zdenerwowaliście :roll2: Ja właśnie starałem się bronić tej elastyczności laugh.gif To Ty @bigZbig chciałeś chronić Nas przed przypisywaniem wartości przy deklaracji smile.gif
Zresztą nieważne smile.gif
bigZbig
@Cysiaczek - przyznam sie, ze sam czesto nadaje zmiennym wartosci poza konstruktorem, co nie zmienia faktu, ze nie jest to dobra praktyka tylko moje lenistwo.
Cysiaczek
Tia. Każdy ma coś za uszami biggrin.gif Najczęściej zdarza mi się przekombinować klasę smile.gif i jeszcze zdarza mi się robic estricty hehe
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.