问题
I am writing a php app with subclasses and since I want to have multiple ways to create an object I am doing different factory methods instead of multiple constructors.
I have a User
with factory methods
User::from_id
User::from_netid
I have several subclasses of User
. I was previously calling the parent superconstructor, but when I switched to the factory method that constructor didn't exist.
I have Student
, a subclass of User
. To get it to work, I had to duplicate almost all of my superclass factory code in User::from_id
to load_by_id
, since in this situation the instance already existed:
// 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;
...
}
I want to call the superclass factory method from the subclass as a starting point, and then continue to add the other fields. Something like this...
$instance = User::from_id($id);
or
$instance = Student::from_id($id);
but in these cases it gives me a User
object, and I need a Student
object. The only way I could accomplish this is by doing $instance = new self()
.
How can I call the superclass factory method from the subclass as a starting point to create a new subclass factory method?
回答1:
Your problem is this:
$instance = new self();
self
refers to the class where the method is defined, not the caller:
- When
Student::from_id()
is called, if it doesn't exist, it falls back toUser::from_id()
. - In
User::from_id()
,self
refers toUser
, notStudent
.
You'd have to use late-static bindings:
$instance = new static();
However, like I always do, I'd highly recommend against it. You're better off using the object scope than the static scope. It's easier to extend, to fake or mock and incidentally, to test.
There's nothing wrong with:
$user = new User;
$user->from_id($id);
$student = new Student;
$student->from_id($id);
...it's actually better.
回答2:
If you're using PHP 5.3 or higher, you could use the Late Static Bindings that are now available:
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
Note - you're probably better off setting up a whole factory class for mocking/testing/sanity...
来源:https://stackoverflow.com/questions/8583989/php-call-superclass-factory-method-from-subclass-factory-method