Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [OOP] konstruktor ?
Forum PHP.pl > Forum > PHP > Object-oriented programming
piraciq
Witam,

Może to i nie miejsce na to, a może i tak? Takie pytanie teoretycznie:

Czy w konstruktorze klasy należy umieszczać wszystkie dane które trafiają do klasy czy tylko te które ulegają przetworzeniu przez tą klasę??

pozdrawiam
skowron-line
Takie które trafiają do klasy przy tworzeniu obiektu.
mike
Konstruktor klasy służy do skonstuowania obiektu. Co oznacza że powinieneś przekazać do niego tylko te dane, która są wymagane do powstania instancji.
piraciq
dajmy na to przy rejestracji usera::


login haslo w zasadzie tyle wystarczy prawda questionmark.gif

ale jesli mamy w formularzu rejestracji inne pola questionmark.gif komunikator stronę www??
mike
Cytat(piraciq @ 14.07.2008, 15:46:47 ) *
dajmy na to przy rejestracji usera::
login haslo w zasadzie tyle wystarczy prawda questionmark.gif
Źle.

Załóżmy że rejestrujesz za pomocą klasy User. Do stworzenia takiego obiektu wcale nie potrzebujesz hasła czy loginu.
Powinno byc raczej rak:
  1. <?php
  2.  
  3. /* @var $user User */
  4. $user = new User();
  5. $user->setName('użytkownik');
  6. $user->setPassword('hasło');
  7. $user->registerNewUser();
  8.  
  9. ?>
piraciq
Cytat(mike @ 14.07.2008, 16:00:50 ) *
Źle.

Załóżmy że rejestrujesz za pomocą klasy User. Do stworzenia takiego obiektu wcale nie potrzebujesz hasła czy loginu.
Powinno byc raczej rak:
  1. <?php
  2.  
  3. /* @var $user User */
  4. $user = new User();
  5. $user->setName('użytkownik');
  6. $user->setPassword('hasło');
  7. $user->registerNewUser();
  8.  
  9. ?>

chodzi mi o sam konstruktor klasy "user" co w takim przypadku powinno sie w nim znajdować bo z tego co Ty napisałeś domyślam się, że w konstruktorze się nic nie znajduje tak questionmark.gif

  1. <?php
  2. public function __construct
  3. {}
  4. ?>
mike
W podanym przez Ciebie przykładzie tak, konstruktor byłby pusty. Ale to wszystko zależy czym u Ciebie jest User i jak działa.
Wystarczy przykład lekko zmodyfikować i masz konstruktor wypełniony.
  1. <?php
  2.  
  3. class User {
  4. private $name;
  5. private $password;
  6. private $gg;
  7. // ... etc
  8.  
  9. public function __construct($id = null) {
  10. if ($id !== null) {
  11. $user = User::retrieveById($id);
  12. $this->fillUser($user);
  13. }
  14. }
  15.  
  16. public static function retrieveById($id) {
  17. // funkcja pobiera z bazy danych użytkownika i zwraca go jako obiekt
  18. }
  19.  
  20. public function fillUser(User $user) {
  21. // funkcja wypełnia pola obiektu polami z przekazanego obiektu;
  22. }
  23.  
  24. }
  25.  
  26. ?>

I teraz możesz zrobić:
  1. <?php
  2.  
  3. // nowy użytkownik
  4. $newUser = new User();
  5.  
  6. // pobranie istniejącego użytkownika
  7. $existingUser = new User(12);
  8. // wykonanie poyższego konstruktowa byłoby tym samym co:
  9. $existingUser = User::retrieveById(12);
  10. // ale to w końcu przykład
  11.  
  12. ?>



Jak widzisz do konstruktora przekazuje się to co jest potrzebne a nie tyle ile się da. Czasem oczywiście do stworzenia obiektu nic nie jest potrzebne.
Wtedy konstruktor nic nie robi. i może być pusty lub w ogóle może go nie być.
piraciq
Dzięki za nakierowanie mnie :]

jeśli napotkam na jakieś pytania napiszę jeszcze raz dzieki
Sedziwoj
To co podał mike jest ładnym przykładem (sam bym podał gdybym był wcześniej, ach ten Propel tongue.gif), ale ogólnie zasiada jest taka, że projektujesz sobie jakiś obiekt, i wiesz że nie może on zacząć działać bez pewnych danych, więc aby wymusić aby zawsze były, przyjmujesz w konstruktorze.
Tak jak masz definicję klasy obsługującej jedno połączenie, to wiadomo, że potrzebne jest do czego się łączy (czy to soap czy pdt ), oczywiście można dać metodę która to ustawia, ale przez to zawsze musiał byś sprawdzać czy już zostało podane, czy jeszcze nie. Ale jest zasada, konstruktor (jak i każda metoda) muszą być jak najprostsze, czyli jak już coś przyjmujesz, to staraj się jak najmniej, tyle ile jest niezbędne.
piraciq
W przypadku klas do obsługi baz danych to jest dla mnie zrozumiałe co się znajduje w konstruktorze klasy. Ale właśnie mam problem ze zrozumieniem tej filozofii kiedy przekazywać dane do konstruktora a kiedy nie?? Jest na to jakaś reguła czy nie questionmark.gif
mike
Jest reguła. Powtórzę: przekazujesz to co jest niezbędne.
A niewiele rzeczy jest niezbędnych, więc staraj się być minimalistą w tym zagadnieniu.
piraciq
No to zobaczymy co mi z tego wyjdzie :]

  1. <?php
  2. class register extends sql
  3. {
  4.  
  5.  
  6. public function __construct($email,$pass,$pass_replace,$nick,$minlenghtpass)
  7. {
  8. $this->user_email=trim($email);
  9. $this->user_pass=trim($pass);
  10. $this->user_pass_replace=trim($pass_replace);
  11. $this->user_nick=trim($nick);
  12. $this->minlenghtpass=$minlenghtpass;
  13. }
  14. private function licz_wiersze($query)
  15. {
  16. return mysql_num_rows($query);
  17. }
  18. public function sprawdz_email_w_bazie($email)
  19. {
  20.  
  21. $zap=$this->query("select user_email from users where user_email='".$this->user_email."'");
  22. return $this->licz_wiersze($zap);
  23.  
  24. }
  25.  
  26. public function poprawnosc_email ($email)
  27. {
  28. if (eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$",$email))
  29. {
  30. return true;
  31. }
  32. else
  33. {
  34. return false;
  35. }
  36.  
  37. }
  38. public function dlugosc_hasla ($pass)
  39. {
  40. if (strlen($pass)<=$this->minlenghtpass)
  41. {
  42. return false;
  43. }
  44. else
  45. {
  46. return true;
  47. }
  48. }
  49. public function sprawdzanie_hasla($pass,$pass_replace)
  50. {
  51.  return ($this->user_pass==$this->user_pass_replace ? true : false )
  52.  
  53. }
  54.  
  55. }
  56.  
  57. $register= new register($_POST['email'],$_POST['pass'],$_POST['pass_replace'],$_POST['nick'],'5');
  58. ?>


i czy tu jest za dużo zmiennych przekazywanych do konstruktora questionmark.gif
Cysiaczek
Nie, może być tak, choć ja bym się zastanowił nad przekazaniem tablicy zamiast osobnych argumentów.
Taka rejestracja ma charakter potencjalnie zmienny, więc array byłby na pewno lepszy smile.gif

Pozdrawiam.
wlamywacz
Łatwiej chyba takie coś:
  1. <?php
  2. public function setParam($name, $param) {
  3.  
  4. $this->$name = $param;
  5. }
  6.  
  7. $db = new db;
  8. $db->setParam('user', $ini_array['mysql']['user']);
  9. $db->setParam('pass', $ini_array['mysql']['pass']);
  10. $db->setParam('name', $ini_array['mysql']['name']);
  11. $db->setParam('host', $ini_array['mysql']['host']);
  12. $db->connect();
  13. ?>


Poza tym nie rozumiem czemu dziedziczysz klasę odpowiedzialną za bazę danych ?
Sedziwoj
@piraciq
Pomijam konstruktor, bo jak patrzę na takie coś, to się zastanawiam po co ten obiekt, chyba tylko aby był.
Przecież jak tworzysz obiekt, to po to aby ułatwić sobie życie, a to co prezentujesz, to zebranie funkcji i zmiennych w jedno pudełko.
Co do propozycji tablicy, to moim zdaniem jest to nie eleganckie, wiadomo jak obiekt obrabia dane z POST/GET to ma tablice, ale dalej dane o konkretnej strukturze, powinny być inaczej rozpowszechniane. Czy to przez obiekt danych (w tym przypadku, nadmiar formy, nad treścią), czy też po prostu przekazywane pojedynczo przez set'ery. A taki obiekt rejestracji jak dostaje te dane to od razu je sprawdza, czy są poprawne, nie ktoś kto go używa ma sam "uruchamiać" sprawdzanie.
Cysiaczek
Może i tablica do konstruktora to nie najlepszy pomysł, ale już tablica przez setter wydaje mi się sensowna. Sprawdzasz wtedy strukturę takiej tablicy i masz wszystko w jednym miejscu. Troszkę jak propelowe fromArray() przy wypełnianiu obiektu. Uważam, że zwłaszcza przy obiektach, które nie są udostępniane użytkownikowi jako interfejs, takie coś doskonale przyspiesza. Można się też pokusić o specjalny obiekt zamiast tablicy - Parameters smile.gif
heh, tylko po co tutaj...
piraciq
Cytat(wlamywacz @ 17.07.2008, 20:22:01 ) *
Łatwiej chyba takie coś:
  1. <?php
  2. public function setParam($name, $param) {
  3.  
  4. $this->$name = $param;
  5. }
  6.  
  7. $db = new db;
  8. $db->setParam('user', $ini_array['mysql']['user']);
  9. $db->setParam('pass', $ini_array['mysql']['pass']);
  10. $db->setParam('name', $ini_array['mysql']['name']);
  11. $db->setParam('host', $ini_array['mysql']['host']);
  12. $db->connect();
  13. ?>


Poza tym nie rozumiem czemu dziedziczysz klasę odpowiedzialną za bazę danych ?

to był przykład książkowy dziedziczenie klas, każde wskazówki są mile widziane :]
dzięki

opierałem się na tym
Neojawor
może trochę się czepiam i nie na temat, ale masz kod:
  1. <?php
  2. private function licz_wiersze($query)
  3.    {
  4.        return mysql_num_rows($query);
  5.    }
  6. ?>

wszystko w nim dobrze, ale mysql_num_rows wymaga jako parametru wyniku zapytania, a parametr $query sugeruje, że będziesz chciał tam wsadzić treść zapytania.

Wracając do tematu, to register nie pasuje mi na klasę. Klasa ma być opisem jakiejś rzeczywistej rzeczy, a register to czynność. IMHO bardziej pasuje tu stworzenie klasy user, który będzie miał metodę register dodającą obiekt tej klasy do bazy.
mecenas
w kwestii konstruktora - jest to kwintesencja OOP i w zasadzie bez tego nie można mówić o obiektowości.
Jaki jest sens konstruktora w oderwaniu od baz danych? Ma dokładnie takie samo znaczenie. W razie poważniejszych problemów ze zrozumieniem tego polecam lekturę teorii innych języków obiektowych - być może wyjście z poletka php ułatwi zadanie, a przecież w wielkim stopniu język jest sprawą wtórną smile.gif

btw - witam smile.gif
Cysiaczek
Również witam smile.gif

Cytat
w kwestii konstruktora - jest to kwintesencja OOP i w zasadzie bez tego nie można mówić o obiektowości.

Czyli jak nie ma konstruktora, to nie ma OOP? Wybacz, ale jestem w stanie napisać kod w pełni obiektowy bez użycia choćby jednego konstruktora, więc dziwne masz to kryterium obiektowości.
mecenas
zależy co rozumiesz przez konstruktor - bo w najogólniejszym przypadku jakikolwiek program bez konstruktora nie miałby najmniejszego sensu, bo... generalnie po cóż program bez zmiennych? Oczywiście w tym momencie można by się przyczepić, że w takim ogólnym znaczeniu konstruktory przecież funkcjonują we właściwie każdym języku, niezależnie od metody programowania...

Masz rację, może niezbyt precyzyjnie się wyraziłem. Zakładam, że chodzi Ci o własne konstruktory tworzonych przez programistę klas. A i owszem, można pisać obiektowo bez wykorzystania konstruktorów, tylko po co? Wydaje mi się i nie jestem odosobniony w tej opinii, że to miała być jedna z podstawowych zalet takiej filozofii programowania.

Może powinniśmy przed rozpoczęciem dyskusji zdefiniować czym dla nas jest obiekt? Dla mnie jest to typ (niekoniecznie złożony) wraz z jego metodami...

Oczywiście wszelkie dywagacje wolałbym dla własnego bezpieczeństwa oderwać od języka.
mike
Cytat(mecenas @ 24.09.2008, 14:54:31 ) *
zależy co rozumiesz przez konstruktor - bo w najogólniejszym przypadku jakikolwiek program bez konstruktora nie miałby najmniejszego sensu, bo... generalnie po cóż program bez zmiennych?
Zdecyduj się o czym piszesz. O konstruktorach czy o zmiennych. To są całkiem inne pojęcia.
Cytat(mecenas @ 24.09.2008, 14:54:31 ) *
A i owszem, można pisać obiektowo bez wykorzystania konstruktorów, tylko po co? Wydaje mi się i nie jestem odosobniony w tej opinii, że to miała być jedna z podstawowych zalet takiej filozofii programowania.
Po to samo jak w każdym innym przypadku. I jeśli chodzi o moją opinię to konstruktory nie zawsze są potrzebne. Nie można mowić, że paradygmaty OOP wymagają ich istnienie.
Inna sprawa, że świadomy programista powinien ich używać. Czasem nawet jeśli mają być puste.
Cytat(mecenas @ 24.09.2008, 14:54:31 ) *
Może powinniśmy przed rozpoczęciem dyskusji zdefiniować czym dla nas jest obiekt? Dla mnie jest to typ złożony wraz z jego metodami...
Obiekt to byt złożony danych i metod które definiują zachowanie obiektu. Dodatkowo każdy obiekt jest reprezentacją pewnej klasy oraz jest identyfikowalny.


Konstruktor nie zawsze jest potrzebny. Jak sama jego nazwa służy on do konstruowania obiektu na jego starcie. A nie zawsze jest taka konieczność. Wobraź sobie obiekt, który jest zaprojektowany to operacji na innym obiekcie. Możesz go napisać tak by posiadał tylko metodę do przekazania mu danych i metody, które operują na danych. Konstruktor może być zbędny.
mecenas
Cytat(mike @ 24.09.2008, 15:05:00 ) *
Zdecyduj się o czym piszesz. O konstruktorach czy o zmiennych. To są całkiem inne pojęcia.

Chodzi o powiązanie konstruktora i zmiennej i fakt, ze przy tworzeniu każdej zmiennej de facto konstruktor zawsze jest używany i tylko o to mi chodziło w tym momencie. Doskonale wiem jaka jest różnica smile.gif
Cytat(mike @ 24.09.2008, 15:05:00 ) *
I jeśli chodzi o moją opinię to konstruktory nie zawsze są potrzebne. Nie można mowić, że paradygmaty OOP wymagają ich istnienie.

Faktycznie tak zabrzmiała moja wypowiedź. Oczywiście, implementacja konstruktora nie jest warunkiem koniecznym do uznania kodu za obiektowy, ale...
Tutaj dochodzimy do wspólnego punktu widzenia:
Cytat(mike @ 24.09.2008, 15:05:00 ) *
Inna sprawa, że świadomy programista powinien ich używać. Czasem nawet jeśli mają być puste.

I w zasadzie tu tkwi cały sens tego wszystkiego - skoro mamy takie dobrodziejstwo, skoro tak wskazują wytyczne - nazwijmy to - 'sztuki programowania', to czemu tego nie robić?

Cytat(mike @ 24.09.2008, 15:05:00 ) *
Obiekt to byt złożony danych i metod które definiują zachowanie obiektu. Dodatkowo każdy obiekt jest reprezentacją pewnej klasy oraz jest identyfikowalny.

Zgoda smile.gif

Cytat(mike @ 24.09.2008, 15:05:00 ) *
Konstruktor nie zawsze jest potrzebny. Jak sama jego nazwa służy on do konstruowania obiektu na jego starcie. A nie zawsze jest taka konieczność. Wobraź sobie obiekt, który jest zaprojektowany to operacji na innym obiekcie. Możesz go napisać tak by posiadał tylko metodę do przekazania mu danych i metody, które operują na danych. Konstruktor może być zbędny.

Jasne, że może być zbędny, ale jest to jednak dość specyficzny przypadek, nie sądzisz?
Crozin
Cytat
Chodzi o powiązanie konstruktora i zmiennej i fakt, ze przy tworzeniu każdej zmiennej de facto konstruktor zawsze jest używany
  1. <?
  2. $zmienna = 'wartosc';
  3. ?>
Nie widzę tu nigdzie wywołania, żadnego konstruktora. Może chodzi Ci o
  1. <?
  2. $obj = new abcdef();
  3. ?>
Ale tutaj nazwanie $obj zmienna jest trochę dziwne. No i konstruktor nie zawsze jest używany. Jedynie wtedy, gdy jest on zaimplementowany w klasie/klasie rodzicu.
Cytat
Jasne, że może być zbędny, ale jest to jednak dość specyficzny przypadek, nie sądzisz?
Nie, nie jest to dość specyficzny przypadek.
mecenas
Cytat(Crozin @ 24.09.2008, 21:49:47 ) *
  1. <?php
  2. $zmienna = 'wartosc';
  3. ?>

Nie widzę tu nigdzie wywołania, żadnego konstruktora.

To, że nie widać jawnie wywołania konstruktora nie oznacza, że takowe się nie odbywa. W takim przypadku zajmuje się tym po prostu interpreter php, który sam zajmuje się konstrukcją takiego prostego typu. Owszem - odchodzę nieco od tematu i oczywiście akurat ten typ konstrukcji nie jest jakimś szczególnie obiektowym zjawiskiem.

Cytat(Crozin @ 24.09.2008, 21:49:47 ) *
Może chodzi Ci o
  1. <?php
  2. $obj = new abcdef();
  3. ?>
Ale tutaj nazwanie $obj zmienna jest trochę dziwne. No i konstruktor nie zawsze jest używany. Jedynie wtedy, gdy jest on zaimplementowany w klasie/klasie rodzicu.

Mógłbyś wyjaśnić mi cóż w tym dziwnego widzisz?

Cytat(Crozin @ 24.09.2008, 21:49:47 ) *
Nie, nie jest to dość specyficzny przypadek.

To jest chyba dość subiektywny punkt widzenia. Dobrze, że możemy mieć inny - różnica mam nadzieję będzie budująca smile.gif

Osobiście jak sięgam pamięcią nie kojarzę, żeby zdarzyło mi się tworzyć klasy bez konstruktorów. Co więcej - dokładnie tak byłem uczony. Oczywiście moje poglądy mogą wypływać z typu oprogramowania i używanych przeze mnie języków. Nie ukrywam, że jeśli chodzi o php to w tej chwili jest to dla mnie dość interesująca, niemniej wciąż tylko zabawa. Dużo większe doświadczenie mam z c++ i c#, pisywałem głównie różne sofciki bazodanowe, numeryczne i odrobinę sieciowych.

Mam nadzieję nauczyć się od Was czegoś ciekawego smile.gif
dr_bonzo
Co do koniecznosci definiowania konstruktorow, szybkie statystyki z mojego projektu:

Kod
$ find . -name "*.php" | xargs grep -E "^class" | wc -l
     219
$ find . -name "*.php" | xargs grep -E "__construct" | wc -l
      86


Czyli (w przyblizeniu, bo zliczanie nei bylo dokladnie) mam konstruktor w mniej niz 50% klas, a w OOP nie jestem (nieskromnie) cienki smile.gif
wrzasq
@Crozin: chyba sie troche zagalopowales z tymi przykladami winksmiley.jpg.

@mecenas: ja, tak jak poprzednicy uwazam, ze konstruktor nie jest wymogiem aby mowic o obiektowosci. jasne ze jest on bardzo przydatny i bardzo wazny, ale jego brak nie implikuje braku obiektowosci. mozna by sobie na przyklad wyobrazic sytuacje, gdy programista musi po prostu jawnie wywolywac jakas metode inicjujaca zamiast niejawnego wywolania konstruktora. umozliwia on oczywiscie wiele bardziej zlozonych konstrukcji i wieksza kontrole, ale same podstawy obiektowosci moim zdaniem sa realizowane i bez niego winksmiley.jpg. inna sprawa, ze owszem - PHP jest specyficzne. tutaj bardzo zadko konstruktor jest czyms niezbednym, zazwyczaj conajwyzej daje mozliwosc automatycznego ustawienia obiektu pod konkretna sytuacje, ale jego operacje nie sa niezbedne do tworzenia obiektu i jego funkcjonowania. owszem w C++, C#, czy na przyklad w Object Pascal/Delphi inaczej sie to postrzega, chociazby w Object Pascal'u gdzie tworzenie instancji klasy wymaga jawnego wywolania konstruktora, ale w PHP obiektowosc i tak jest uposledzona winksmiley.jpg.
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.