PHP5 Overloading af constructors
aug 10
Jeg sidder i skrivende stund og forsøger at forbedre mine evner med OOP i PHP5. Og har man første sagt OOP, kommer man vel ikke uden om at sige constructor og overloading af samme … eller hvad?!
Da PHP5 udkom, var der en del hype om forbedringer i henhold til at kode objekt orienteret heri, der er bl.a. introduceret en ny måde at lave constructors på samt mulighed for at bestemme public/private/protected identifyers til funktioner.
Hvor man i PHP4 blot skulle defineret constructors som en funktion med samme navn som klassen, kan man nu bruge __construct() og evt. __destruct() – men hvad med overloading af constructors?
I sprog som f.eks. C# og Java overloader du constructors blot ved at tilføje endnu en funktion med klassens navn, og med et unikt antal parametre:
class Test {
public Test() {
//Default constructor
}
public Test(int foo) {
//Constructor using 1 parameter
}
public Test(int foo, int bar) {
//Constructor using 2 parameters
}
}
Det skulle være forholdsvis let at komme til at tro, at man kunne udføre noget lignende i PHP5, nu det jo er kommet med på noderne
- men sådan forholder det sig ikke helt. Jeg forsøgte f.eks. til at starte med, at lave en overloading ved noget ligende:
public function __construct($foo) {
//Constructor using 1 parameter
}
Men da jeg samtidig havde defineret en standard constructor, fik jeg en fejlmelding:
Fatal error: Cannot redeclare Test::__construct()
Underligt tænkte jeg, og begyndte at Google overloading af constructors lidt. Og det lader åbenbart til at være et generelt problem/irritationsmoment.
Constructor overloading work-around
Jeg fandt dog frem til følgende work-around, hvilket virker udemærket – men ærlig talt, hvorfor har man dog lader et så basal ting udeblive i et sprog nu man alligevel var igang med at forbedre dets muligheder for OOP?!
public function __construct() {
$num = func_num_args();
$args = func_get_args();
switch($num) {
case 1:
$this->__call(__construct1, $args);
break;
case 2:
$this->__call(__construct2, $args);
default:
//Do default stuff
}
}
Ved at "switche" på antallet af input parametre til constructoren (også selvom man ikke skal definere dem i selve constructoren – WTF?), og benytte en interne function __call, som meget simpelt kalder en anden funktion med de sendte input paramtre, kan man få sin kode til at "se ud til" man overloader constructoren.
I virkeligheden kalder vi bare nogle andre funktioner, her meget søgt kaldet __construct1/2/3, alt efter antallet af parametre.
public function __construct1($param) {
//do stuff with your one parameter
}
public function __construct2($param1, $param2) {
//do stuff with 2 parameters!
}
Funktionen til at kalde vores "overloadede constructors" ser ud således:
private function __call($name, $arg) {
return call_user_func_array(array($this, $name), $arg);
}
Løsningen fungere udemærket, om ikke andet er det da rimelig transparent for den der efterfølgende skal bruger klassen… Ved ikke helt hvad jeg synes om det, men indtil andet er på plads (i PHP), så vil jeg tro dette er måden at gøre det på.
Er der nogen der er kommet frem til andre måder at overloade constructors på i PHP?
RSS
Twitter
Flickr
Facebook





feb 08, 2009 @ 03:58:18
Kan du ikke bare gøre følgende?
public static function MyMethod($myRequiredArgument, $optionalArgument = NULL) {
// My code
}
feb 08, 2009 @ 11:14:07
Hej Simon,
Jo det kunne jeg sådan set godt. Men man kunne jo godt forestille sig f.eks. en Bruger-klasse hvor default constructoren tog en enkelt parameter (f.eks. ID), og en overloaded constructor tog 2 parametre (f.eks. brugernavn, password). Parameterne kunne være af forkellige datatyper (selvom det jo ikke helt holder i PHP), og uanset hvad vil du skulle til at kode “cases” i din funktion alt efter hvile parametre der er sat …
Jeg synes det er “pænere” om ikke andet mere overskueligt hvis jeg har mulighed for at adskille mine funktioner… Just my 5 cents
feb 09, 2009 @ 11:50:49
Hej Simon.
Det er også den rigtige måde at gøre det på, ihvertilfald hvis du tænker OOP eller hvordan det gøres i andre sprog. Jeg vælger dog at gøre det på måden som nævnt i #1, da det giver mindre kode.
public function user($userID, $userName = NULL, $password = NULL) {
if($userName && $password) {
// Udfør kode baseret på username,password
}
}
Hehe i øvrigt fedt site. Eneste minus er FCKeditor. Den er svær at skrive kodeeksempler i..
PS: Du bør sætte op i config filen for FCKEditor, at den ikke skal lave <p> på linjebrud men i stedet <br>. Det kunne ihvertilfald være en fed ting
Hilsen
Simon
feb 09, 2009 @ 22:12:53
#3: Det giver mindre kode til den klasse du skriver “nu” – men skal du genbruge den klasse i et andet eksempel, kunne det let være at du skulle til at ændre dine funktioner – så ville det være lettere at have dem mere adskildt
PS: Jeg bruger pt. ikke FCKeditor, men er gået over til TinyMCE til kommenteret – og jeps, er ikke det nemmeste at skrive kode i, beklager.
feb 10, 2009 @ 13:05:03
#4
Jeg vil give dig ret i, at det er en funktion der burde komme (og nok også kommer i PHP6 med namespaces osv) – men mener ikke det er et problem som sådan. Det ville have været et problem, hvis PHP i forvejen overholdte datatyper og så videre – men det ville samtidig give et kæmpe problem for mange PHP brugere som ikke er bekendt med OOP.
Problem: nej – nice2have: helt sikkert