slash12345
10.07.2006, 23:35:30
Witam,
Mam taką klasę w php:
<?php
class test{
public $a = 0;
public $b = $a;
}
?>
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
10.07.2006, 23:53:01
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:
<?php
class test {
public $a = 0;
public $b;
public function __construct()
{
$this->b = $this->a;
}
}
?>
bigZbig
11.07.2006, 06:38:29
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
11.07.2006, 06:46:09
A co, jeśli będę chciał mieć tak:
<?php
class cysio{
public $path='/ble/ble/ble/';
public function __construct(){
$data=file_get_conte ... //bierzemy coś z pliku
$this->path='/ble/ble/ble/kolejne/ble/';
}
}
?>
Może niezbyt uzyteczny przykład

, ale w zasadzie jest uzasadnione przypisanie wartości przy deklaracji czy nie?
bigZbig
11.07.2006, 07:50:30
@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?
<?php
class cysio{
public $path;
public function __construct(){
$this->path = '/ble/ble/ble/';
$data=file_get_conte ... //bierzemy coś z pliku
$this->path = '/ble/ble/ble/kolejne/ble/';
}
}
?>
Cysiaczek
11.07.2006, 07:59:40
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
bigZbig
11.07.2006, 08:11:34
1. Dlaczego mialbym usuwac konstruktor z klasy skoro juz w niej jest?
2. Czy w klasie abstrakcyjnej nie mozna stworzyc konstruktora?
Cysiaczek
11.07.2006, 08:18:11
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])
mike
11.07.2006, 08:24:49
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
11.07.2006, 08:33:25
OOpsssaaa. Pomyłka
Jak się nie zdefiniuje konstruktora w pochodnej, to z bazowej jest przecież wywoływany automatycznie.
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.

Aha. W jakimś topiku pisałem na temat prywatnego konstruktora. Już mam kontekst

Napiszę tutaj, bo częsciowo temat pasuje.
<?php
abstract class CoolPeople{
private function __construct(){
}
abstract function beCool();
}
class cysio extends CoolPeople{
public function __construct(){
parent::__construct();
}
function beCool(){}
}
$ob=new cysio;
?>
...A teraz usuńcie cały konstruktor z klasy pochodnej i juz error gotowy :|
Ludvik
11.07.2006, 09:23:34
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
11.07.2006, 09:36:18
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...

to chyba nigdy nie nastapi
Ludvik
11.07.2006, 09:46:05
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
11.07.2006, 09:54:35
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

. Zresztą... nie znam się aż tak dobrze.
Jak ktoś ma pomysł co zrobic z tym fantem, to niech napisze
Ludvik
11.07.2006, 10:03:23
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ć

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
Cysiaczek
11.07.2006, 10:14:14
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
11.07.2006, 10:35:43
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
11.07.2006, 10:42:28
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
11.07.2006, 10:56:35
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
11.07.2006, 11:02:16
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
Cysiaczek
11.07.2006, 11:26:05
@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
11.07.2006, 11:57:09
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
11.07.2006, 12:14:19
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
11.07.2006, 12:23:36
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

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
11.07.2006, 12:43:24
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
11.07.2006, 13:02:25
Ale się zdenerwowaliście :roll2: Ja właśnie starałem się bronić tej elastyczności

To Ty @bigZbig chciałeś chronić Nas przed przypisywaniem wartości przy deklaracji

Zresztą nieważne
bigZbig
11.07.2006, 13:26:03
@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
11.07.2006, 13:30:43
Tia. Każdy ma coś za uszami

Najczęściej zdarza mi się przekombinować klasę

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.