【问题标题】:PHP static factory method: dynamically instantiate instance of the calling classPHP静态工厂方法:动态实例化调用类的实例
【发布时间】:2015-04-16 05:33:40
【问题描述】:

这个 PHP 问题与 this question 有关,但有点不同。我有一个名为create() 的静态工厂方法,它实例化一个类实例。我希望该方法动态实例化调用它的(子)类的实例。因此,它实例化的类必须在运行时确定。但是我想这样做而不必重新定义子类中的静态工厂方法(这在我的示例中完全有效,因为子类没有要初始化的新数据成员)。这有可能吗?

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.

【问题讨论】:

    标签: php static runtime subclass factory


    【解决方案1】:

    您必须使用 Late Static Binding 创建对象 - 方法 get_called_class() 很有用。第二种选择是使用 static 关键字。

    例子:

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

    然后输出:

    Joe
    Hello, Joe
    

    【讨论】:

    • 因为您必须创建对象SubFoo,请阅读后期状态绑定...并且有一个问题。 static也不错。
    • 对不起,我的意思是 static 不是 self
    • 什么不赞成?我没有投反对票。如果我不小心投了反对票,然后在十分之一秒后又投了赞成票,那可能会出现在某个地方,不确定在这种情况下 SE 代码是否会删除通知。无论如何,如果有人反对,那不是我。问候。
    • 无论如何,使用get_called_class() 代替static 有什么好处?谢谢。
    • get_called_class() 可用于检索带有被调用类名称的字符串,但 static 正在创建对象。
    【解决方案2】:

    return new static();

    已经有保留关键字static

    【讨论】:

    • 嗯,这对我不起作用。第一次调用很好,但是当我调用$subFoo->getHelloName() 时,我收到了致命错误Call to undefined method Foo::getHelloName()。看起来self 在编译时绑定,而不是在运行时绑定,因为我需要它来绑定。我已经更新了我的代码以显示这一点。
    • 对不起,我的错,这是static关键字
    • 好的,return new static($name) 为我工作。请更新您的答案,以便我接受。谢谢。
    【解决方案3】:

    是的,可以通过 php 的后期静态绑定功能实现。

    代替

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

    试试这个

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

    【讨论】:

    • 好吧,如果我有一个子类链 parent 无论如何都不会工作。我认为使用static($parameterList) 是我所寻找的最佳答案。
    猜你喜欢
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    相关资源
    最近更新 更多