PHP从子类工厂方法调用超类工厂方法

jke*_*esh 1 php subclass factory-pattern superclass

我正在编写一个带有子类的php应用程序,因为我想有多种方法来创建一个对象,我正在做不同的工厂方法而不是多个构造函数.

我有一个User工厂方法

User::from_id
User::from_netid
Run Code Online (Sandbox Code Playgroud)

我有几个子类User.我之前调用了父超级构造函数,但是当我切换到工厂方法时,构造函数不存在.

我有Student,一个子类User.为了使它工作,我不得不将几乎所有的超类工厂代码复制User::from_idload_by_id,因为在这种情况下实例已经存在:

// In Student.php - Student extends User
public static function from_id_and_course($id, $course){
    $instance = new self();
    $instance->load_by_id($id);
    $instance->course = $course;
    ...
}
Run Code Online (Sandbox Code Playgroud)

我想从子类中调用超类工厂方法作为起点,然后继续添加其他字段.像这样......

$instance = User::from_id($id);
Run Code Online (Sandbox Code Playgroud)

要么

$instance = Student::from_id($id);
Run Code Online (Sandbox Code Playgroud)

但在这些情况下,它给了我一个User对象,我需要一个Student对象.我能做到这一点的唯一方法就是这样做$instance = new self().

如何从子类中调用超类工厂方法作为创建新子类工厂方法的起点?

net*_*der 5

你的问题是这样的:

$instance = new self();
Run Code Online (Sandbox Code Playgroud)

self 是指定义方法的类,而不是调用者:

  • Student::from_id()被调用时,如果它不存在,它就会回落User::from_id().
  • User::from_id(),selfUser,不是Student.

您必须使用后期静态绑定:

$instance = new static();
Run Code Online (Sandbox Code Playgroud)

然而,就像我一直这样,我强烈建议反对它.您最好使用对象范围而不是静态范围.它更容易扩展,虚假或模拟和偶然的测试.

没有错:

$user = new User;
$user->from_id($id);

$student = new Student;
$student->from_id($id);
Run Code Online (Sandbox Code Playgroud)

......它实际上更好.