Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Przeciążanie konstruktora
Forum PHP.pl > Forum > PHP > Object-oriented programming
athabus
Mam pytanie czy w php5 da się przeciążyć konstruktor? Generalnie wiem, że można przeciążać dowolną funkcję za pomocą __call, ale z konstruktorem jakos mi nie wychodzi mad.gif

Próbowałem zarówno użyć __construct jak i NazwaKlasy przy przeciążaniu w __call i nic z tego. Czy ktos wie jak można przeciążyć konstruktor?
ennics
rzuć jakiś kod i napisz w jakim celu chcesz go przeciążyć.
odwoływałeś siędo niego przez self::__construct() ?
ikioloak
Konstruktor przeciazasz w normalny sposob jak kazda inna metode. Tutaj przyklad:
  1. <?php
  2.  
  3. class foo
  4. {
  5. public function __construct()
  6. {
  7. print "foo<br>";
  8. }
  9. }
  10.  
  11. class fooEx extends foo
  12. {
  13. public function __construct()
  14. {
  15. parent::__construct();
  16. print "fooEx";
  17. }
  18. }
  19.  
  20. $foo = new foo();
  21. $fooex = new fooEx();
  22.  
  23. ?>

Wynik:
Kod
foo
foo
fooEx

oczywiscie parent::__construct(); jest tutaj niepotrzebny, dalem tylko zeby bylo widac ze jakikolwiek zwiazek z klasa nadrzedna istnieje.
athabus
@ikioloak - chodzi mi raczej o przeciazenie konstruktora klasy tak aby moc go wywyolywac z roznymi parametrami (w innych jezykach to jest mozliwe nie wiem czy w php) - nie o dziedziczenie

@all

Podam przyklad co mniej wiecej chce zrobic. W takim razie zalozmy ze tworze klase o nazwie cls_ogloszenie. Bedzie ona zawierala tresc ogloszenia publikowana przez usera lub odczytana z bazy. Teraz musza byc 4 rozne konstruktory:

1) Ktory tworzy ogloszenie z domyslnymi danymi. np __cosntruct()
2) Ktory tworzy ogloszenie na podstawie tablicy asocjacyjnej __construct ($tablica)
3) Ktory tworzy ogloszenie na podstawie id_ogloszenia z danych z formularza np __construct($tytul_ogloszenia, $tresc_ogloszenia itp)
4) Ktory odczytuje ogloszenie z bazy np __construct($bool_odczyt_z_bazy, $id_ogloszenia)


Generalnie chodzi mi o to, ze w zaleznosci od podanej ilosci parametrow bedzie wywolywany odpowiedni konstruktor, ktory cos tam zrobi.

Probowalem takim kodem to zalatwic:
  1. <?php
  2.  
  3. public function __call($metoda, $p)
  4. {
  5.     if ($metoda=="__construct")//tu oczywiscie trzeba jeszcze liste parametrow sprawdzac
  6.     {
  7.         echo "mama";
  8.         throw new Exception ('uruchomiono konstruktor');
  9.     }
  10. }
  11.  
  12. ?>

Wiem ze kod jest jeszcze nie kompletny i trzeba sprawdzac dodatkowo liste parametrow, ale juz nawet w tym przypadku konstruktor jest pomijany -> dla innych funkcji wszystko dziala bez problemu

Nie zabardzo rozumiem o co chodzi z tym self::construct -> gdzie nalezaloby tego uzyc? W php jestem nowy.
ikioloak
Nie wiem czy to jest optymalne rozwiazanie, ale dziala:
  1. <?php
  2.  
  3. class foo
  4. {
  5. public function __construct($p1,$p2,$p3,$p4)
  6. {
  7. if (is_array($p1)) 
  8. {
  9. $this->ConstructFromArray($p1);
  10. }
  11. else if ((is_string($p1))&&(is_string($p2)))
  12. {
  13. $this->ConstructFromUser($p1,$p2);
  14. }
  15. }
  16.  
  17. private function ConstructFromArray($array)
  18. {
  19. print_r($array);
  20. }
  21.  
  22. private function ConstructFromUser($title,$text)
  23. {
  24. print 'tytul:'.$title.' tresc:'.$tresc;
  25. }
  26. }
  27.  
  28.  
  29. $t = array(1,2,4);
  30. $foo = @new foo($t);
  31. $foo2 = @new foo('tytul newsa','tresc newsa');
  32.  
  33. ?>

Inna opcja to jest utworzenei jednej klasy abstrakcyjnej, pozniej 4 klasy gdzie kazda implementuje na swoj sposob konstruktor, i w zaleznosci od parametrow tworzyc obiekt danej klasy. Co o tym mysilsz?
athabus
Tez wlasnie o czym takim myslalem (pierwsze rozwiazanie). Drugie jest nawet ciekawsze winksmiley.jpg
Mam nadziej, ze kiedys w php wprowadza jakies fajne mechanizmy przeciazania takie jak np w C#. Jakos mam uprzedzenie do tych wszystkich if'ow i sprawdzania czy dany parametr jest tablica czy obiektem itd... troche to psuje czytelnosc kodu.

Ale dzieki bardzo za ten drugi sposob - jest calkiem ciekawy: biggrin.gif
orson
witam ...

w php nie można przeciążać funkcji oraz operatorów ... do c++ jeszcze mu daleko ...

co do wywoływania to można w kontruktorze klasy bazowej robić tak: return $this = new klasa_z_parametrow ... to pozwala tworzyć obiekt zawsze przez $foo = new KlasaBazowa ...takie pseudo przeciążanie ...

pozdrawiam
athabus
Cytat
w php nie można przeciążać funkcji oraz operatorów ... do c++ jeszcze mu daleko ...

No funkcje niby mozna przeciazac za pomoca __call($nazwa, $parametry) - ale szczerze to faktycznie nazwanie tego przeciazaniem funckji to naduzycie worriedsmiley.gif

Ja się obiektowego programowania uczylem na C# i teraz mi tych mechanizmow brakuje w php - moze w wersji 6 rozwiaza pare kwestii. Ale moim zdaniem i tak jest o niebo lepiej niz w PHP4
Vengeance
  1. <?php
  2.  
  3.  class FOobar 
  4.  {
  5. public function __construct()
  6. {
  7. $params = func_get_args();
  8. //dalej rob co chccesz
  9. }
  10.  
  11.  }
  12.  
  13. ?>
DeyV
Cytat(orson @ 2005-12-30 16:14:40)
co do wywoływania to można w kontruktorze klasy bazowej robić tak: return $this = new klasa_z_parametrow ... to pozwala tworzyć obiekt zawsze przez $foo = new KlasaBazowa ...takie pseudo

Niestety - nic z tego.
Kontruktor nie może nic zwracać.
Return może zostać użyte tylko bez parametrów, w celu zakończenia działania metody.
orson
witam ...

to w takim razie w php5 się to zmieniło bo pod 4 używam tego w klasie dostępu do danych ... tworze w zależności od wymagań instancję klasy pochodnej mysql lub postgresa ...
a właściwie to nie musi to być w returnie ... można wywalić słowo return i też powinno działać ...

pozdrawiam
yarpo
A to nie możesz stworzyć w klasie bazowej dla obu klas pochodnych (mysql, postgree), metody statycznej, która będzie zwracać odpowiedni obiekt?

Zauważ, że PEAR:biggrin.gifB tak ma:
Kod
$a = DB::connect($dsn);
WaterIntelligence
Można również stworzyć Fabrykę i jest to moim zdaniem najlepsze rozwiązanie dla tworzenia parametryzowanych obiektów. Rozdzielamy odpowiedzialność w czytelny i bardziej intuicyjny sposób.

CODE


class Foo
{
public function __construct()
{ }
}

class FactoryFoo{

public function createFromArray($arr){
$objFoo = new Foo(); $objFoo->p1 = $arr['p1']; // itd
return $objFoo;
}

public function createFromUser($user){ ... }

public function createFromPOSTRequest($arrPost){ ... }

// itd.

}



Unikamy stosowania 'if'.
plurr
WaterIntelligence, nie rozumiem, jak chcesz unikac ifów (ew. case'ów) stosując Factory ? Wg mnie jedno z drugim jest powiazane. Co za tym idzie, aby osiągnać coś na kształt overrida i tak musimy wykonać rzezbe na parametrach konstruktora.
WaterIntelligence
To oczywiście zależy w jakim miejscu budujemy taki obiekt. Możemy przecież zbudować go bezpośrednio wywołując metodę konkretną z fabryki w klasie klienta. Wtedy nie ma w ogóle potrzeby korzystania z 'if'. Podam przykład który zobrazuje o co mi chodziło:

CODE

// Dla fabryki:
class JakisKontroler{
$arr['wypelniacz1'] = $_POST['wypelniacz1'];
$arr['wypelniacz2'] = $_POST['wypelniacz2'];
$obj = $objFabrykaKlasyA->zbudujZtablicy($arr);
}
// sposób na "if'y"
class JakisKontroler{

public function wykonajCos(){
$arr['wypelniacz1'] = $_POST['wypelniacz1'];
$arr['wypelniacz2'] = $_POST['wypelniacz2'];
$obj = new KlasaA($arr); // w konstruktorze wykonuja sie warunki
}
}



Jak widać w pierwszym przypadku w ogóle nie ma 'if' a jedynie wywołanie konkretnej metody, ściśle określonej. Dodatkowo odciążamy klasę od odpowiedzialności budowania obiektu z samej siebie. Klasa moim zdaniem powinna przejmować się tym co ma robić, a nie tym w jaki sposób ma sie "rodzić" - od tego powinny być inne obiekty (oczywiście nie w każdym przypadku ale akurat w tym tak). Co więcej uznaje za złe stosowanie przeciążania ponieważ jest ono niejednoznaczne i łatwo można zapomnieć jakie parametry stosować aby otrzymać to co chcemy, przy stosowaniu metod taki problem nie istnieje bo jest wszystko jasne i przejrzyste.

Jest jeszcze kwestia tego, że przecież nie tylko możemy ustawiać zmienne w tworzonym obiekcie ale wykonywać bardziej złożone operacje podczas budowania obiektu. Więc lepiej trzymać się jednej metodyki wtedy projekt staje się spójny.
markoni
wcale w Factory nie musisz stosować ifów
możesz przecież skorzystać z ReflectionClass
ewentualnie stworzyć obiekt na podstawie zmiennej $object = new $classname();
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.