PHP5 Overloading af constructors

Aug 10, 2008

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?

Comments

comments powered by Disqus