2015-02-15 12 views
5

Diese PHP-Frage bezieht sich auf this question, ist aber ein bisschen anders. Ich habe eine statische Factory-Methode namens create(), die eine Klasseninstanz instanziiert. Ich möchte, dass die Methode eine Instanz der (Sub-) Klasse, auf der sie aufgerufen wird, dynamisch instanziiert. Daher muss die Klasse, die instanziiert wird, zur Laufzeit bestimmt werden. Aber ich möchte dies tun, ohne die statische Factory-Methode in der Unterklasse neu definieren zu müssen (und dies wäre in meinem Beispiel vollkommen gültig, da die Unterklasse keine neuen Datenelemente zum Initialisieren hat). Ist das überhaupt möglich?PHP statische Factory-Methode: Instanz der aufrufenden Klasse dynamisch instanziieren

class Foo { 

    private $name; 

    public static function create($name) { 

    //HERE INSTED OF: 
    return new Foo($name); 
    //I WANT SOMETHING LIKE: 
    //return new get_class($this)($name);//doesn't work 
    //return self($this);//doesn't work either 

    } 

    private function __construct($name) { 

    $this->name = $name; 

    } 

    public function getName() { 

    return $this->name; 

    } 

} 

// the following class has no private data, just extra methods: 

class SubFoo extends Foo { 

    public function getHelloName() { 

    echo "Hello, ", $this->getName(), ".\n"; 

    } 

} 


$foo = Foo::create("Joe"); 
echo $foo->getName(), "\n"; // MUST OUTPUT: Joe 

$subFoo = SubFoo::create("Joe"); 
echo $subFoo->getHelloName(), "\n"; // MUST OUTPUT: Hello, Joe. 

Antwort

5

Sie Objekt Late Static Binding mit erstellen müssen - Methode get_called_class() ist nützlich. Die zweite Option ist static Schlüsselwort.

Beispiel:

class Foo 
{ 
    private $name; 

    public static function create($name) 
    { 
     $object = get_called_class(); 
     return new $object($name); 
    } 

    private function __construct($name) 
    { 
     $this->name = $name; 
    } 

    public function getName() 
    { 
     return $this->name; 
    } 
} 

class SubFoo extends Foo 
{ 
    public function getHelloName() 
    { 
     return "Hello, ". $this->getName(); 
    } 
} 

$foo = Foo::create("Joe"); 
echo $foo->getName(), "\n"; 

$subFoo = SubFoo::create("Joe"); 
echo $subFoo->getHelloName(), "\n"; 

und Ausgang:

Joe 
Hello, Joe 
+1

Weil Sie Objekt 'SubFoo' erstellen müssen, lesen Sie über späte Statusbindung ... Und es gibt einen Punkt der Frage. 'statisch' ist auch gut. –

+1

tschuldigung ich meine 'statisch' nicht' selbst' –

+1

Aber ich verstehe nicht downvote. –

4

return new static();

ist bereits reserviert Stichwort static

+0

Nun, das nicht für mich arbeiten. Der erste Aufruf geht gut, aber wenn ich '$ subFoo-> getHelloName() '' 'rufe, bekomme ich den fatalen Fehler' Aufruf an undefinierte Methode Foo :: getHelloName() '. Es sieht so aus, als ob "self" zur Kompilierzeit und nicht zur Laufzeit bindet, da ich es binden muss. Ich habe meinen Code aktualisiert, um dies zu zeigen. –

+1

oh sorry my bad, es ist 'static' Schlüsselwort –

+0

OK,' return new static ($ name) 'funktioniert für mich. Bitte aktualisieren Sie Ihre Antwort, damit ich sie annehmen kann. Vielen Dank. –

-3

Ja, es ist möglich, mit dem späten statischem Bindung Feature von PHP.

Statt

$foo = Foo::create("Joe"); 
echo $foo->getName(), "\n"; // MUST OUTPUT: Joe 

$subFoo = SubFoo::create("Joe"); 
echo $foo->getHelloName(), "\n"; // MUST OUTPUT: Hello, Joe. 

versuchen, diese

echo parent::getName(); 
echo self::getHelloName(); 
+0

Nun, wenn ich eine Kette von Unterklassen "Eltern" hätte, würde sowieso nicht funktionieren. Ich denke, mit 'static ($ parameterList)' ist die beste Antwort auf das, was ich suchte. –