2015-02-15 46 views
5

To pytanie PHP jest powiązane z this question, ale jest nieco inne. Mam statyczną metodę fabryczną o nazwie create(), która tworzy instancję klasy. Chcę, aby metoda dynamicznie tworzyła instancję klasy (pod), na której jest wywoływana. Tak więc klasa, którą tworzy, musi być określona w czasie wykonywania. Ale chcę to zrobić bez konieczności ponownego zdefiniowania statycznej metody fabryki w podklasie (i byłoby to całkowicie poprawne w moim przykładzie, ponieważ podklasa nie ma żadnych nowych elementów danych do zainicjowania). Czy to w ogóle możliwe?Metoda statycznej fabryki PHP: dynamicznie stwórz instancję klasy wywołującej

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. 

Odpowiedz

5

Musisz utworzyć obiekt za pomocą Late Static Binding - metoda get_called_class() jest przydatna. Druga opcja to użycie słowa kluczowego static.

Przykład:

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"; 

i wyjście:

Joe 
Hello, Joe 
+1

Ponieważ musisz utworzyć obiekt 'SubFoo', przeczytaj o późnym wiązaniu stanu ... I jest pewien punkt zapytania. "static" jest również dobre. –

+1

Przepraszam, mam na myśli 'static' nie' self' –

+1

Ale nie rozumiem. –

4

return new static();

nie jest już zarezerwowana kluczowe static

+0

dobrze, że nie działa dla mnie. Pierwsze wywołanie działa dobrze, ale kiedy nazywam '$ subFoo-> getHelloName()' otrzymuję fatalny błąd 'Call to undefined method Foo :: getHelloName()'. Wygląda na to, że 'self' wiąże się podczas kompilacji, a nie w czasie wykonywania, ponieważ potrzebuję go do wiązania. Zaktualizowałem swój kod, aby to pokazać. –

+1

oh, przepraszam, moje złe, to słowo kluczowe 'statyczne' –

+0

OK,' return new static ($ name) 'działa dla mnie. Zaktualizuj odpowiedź, aby ją zaakceptować. Dzięki. –

-3

Tak, to jest możliwe, z późnego wiązania statycznego cechą php.

Zamiast

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

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

spróbować tej

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

Cóż, jeśli mam łańcuch podklas "rodzic" nie będzie działać tak czy inaczej. Myślę, że używanie 'static ($ parameterList)' jest najlepszą odpowiedzią na to, czego szukałem. –