我正在编写一个带有子类的php应用程序,因为我想有多种方法来创建一个对象,我正在做不同的工厂方法而不是多个构造函数。
我有User
工厂方法
User::from_id
User::from_netid
我有几个User
的子类。我以前调用了父超级构造函数,但是当我切换到工厂方法时,构造函数不存在。
我有Student
,User
的子类。为了使它工作,我不得不将User::from_id
中的几乎所有超类工厂代码复制到load_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;
...
}
我想从子类中调用超类工厂方法作为起点,然后继续添加其他字段。像这样......
$instance = User::from_id($id);
或
$instance = Student::from_id($id);
但在这些情况下它会给我一个User
个对象,我需要一个Student
个对象。我能做到这一点的唯一方法就是做$instance = new self()
。
如何从子类调用超类工厂方法作为创建新子类工厂方法的起点?
答案 0 :(得分:5)
你的问题是:
$instance = new self();
self
是指定义方法的类,而不是调用者:
Student::from_id()
时,如果它不存在,则会回退到User::from_id()
。User::from_id()
中,self
是指User
,而不是Student
。您必须使用late-static bindings:
$instance = new static();
然而,就像我一直这样,我强烈建议不要这样做。您最好使用对象范围而不是静态范围。更容易扩展,虚假或嘲笑,以及顺便进行测试。
没有错:
$user = new User;
$user->from_id($id);
$student = new Student;
$student->from_id($id);
......它实际上更好。
答案 1 :(得分:1)
如果您使用的是PHP 5.3或更高版本,则可以使用现有的Late Static Bindings:
class User
{
public static function from_id($id)
{
// factory
$object = new static();
// setup
// return
return $object;
}
}
class Student extends User { }
$student = Student::from_id($id); // $student should be of class Student
注意 - 你可能最好设置一个完整的工厂类来进行模拟/测试/理智......