PHP:如何从父类的静态方法中调用子类构造函数

11

我希望在父类中拥有一个静态方法,使该方法通过调用的子类创建实例。

以下是一个示例:

class parent {
    public static function make_objects($conditions){
        for (...){
            // 在此处,我想基于特定的$conditions来创建调用make_objects的任何子类的实例
        }
    }
}
class sub extends parent{ ... } $objects = sub::make_objects($some_conditions);

你不是缺少一个 extends 吗?另外,我真的不明白你想做什么。你能给出一个更具说明性的例子来解释 make_objects 返回的内容吗? - Pekka
是的,我缺少一个extends。将会有一个数据库,其中包含无数个子类实例,并且make_objects方法应该根据给定条件返回这些实例的某些子集。基本上,我正在尝试创建类似于ORM工具的东西,但具有我需要的一些特定功能,以用于项目。 - martijnve
4个回答

14

从php 5.3开始,您可以使用static关键字来实现此功能。

<?php
class A {
  public static function newInstance() {
    $rv = new static();  
    return $rv;
  }
}
class B extends A { }
class C extends B { }

$o = A::newInstance(); var_dump($o);
$o = B::newInstance(); var_dump($o);
$o = C::newInstance(); var_dump($o);

打印
object(A)#1 (0) {
}
object(B)#2 (0) {
}
object(C)#1 (0) {
}

编辑:另一个(类似的)例子

<?php
class A {
  public static function newInstance() {
    $rv = new static();  
    return $rv;
  }

  public function __construct() { echo " A::__construct\n"; }
}
class B extends A {
  public function __construct() { echo " B::__construct\n"; }
}
class C extends B {
  public function __construct() { echo " C::__construct\n"; }   
}

$types = array('A', 'B', 'C');
foreach( $types as $t ) {
  echo 't=', $t, "\n";
  $o = $t::newInstance();
  echo '  type of o=', get_class($o), "\n";
}

打印

t=A
 A::__construct
  type of o=A
t=B
 B::__construct
  type of o=B
t=C
 C::__construct
  type of o=C

但是据我所了解,他想根据数据库中的类型创建实例。因此这也无法帮助他。 - Sebastian Hoitz
也许这个问题有点含糊不清,我们等着看吧。 - VolkerK
不,我想创建子行的实例,但是在我的数据库中。所以我认为这就是我一直期望的答案。现在要进行测试。 - martijnve
测试过了,正是我想要的,非常感谢。 - martijnve
如果子构造函数是私有的,怎么办?似乎不起作用。需要使用反射吗? - Peter Ajtai
这个东西在 JavaScript 中也可能吗? - Amarjit Singh

1
我认为你想要这样的东西:
class parent {
  public static function make_object($conditionns) {
    if($conditions == "case1") {
      return new sub();
    }
  }
}

class sub extends parent {

}

现在你可以像这样创建一个实例:

$instance = parent::make_object("case1");

或者

$instance = sub::make_object("case1");

但是,为什么您想让所有子类都扩展父类呢?您不应该更多地拥有您的模型(子类)的父类,然后再有一个工厂类,根据给定的条件创建这些模型的实例吗?


0

嗯,那不是应该这样吗:

class sub extends parent {
  public static function make_objects($conditions) {
    //sub specific stuff here
    //....
  }
}

哦,我明白了,在我的示例代码中忘记了扩展。但不是这样的。创建对象将会非常冗长和复杂,并且将会有数十个父类的子类,因此在每个子类中放置整个方法是极不可取的(尽管它可能会成为唯一的选项)。 - martijnve

-1
将父类设为抽象类,同时将父方法也设为抽象。
abstract static class parent {
     abstract function make_method() {
         // your process
     }
}

class child extends parent {
     public function __construct() {
          parent::make_method();
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接