views:

26

answers:

3

I have a class that has a complex static factory method, lets call it ClassA. I have extended ClassA into ClassB and I want ClassB's factory method to do everything that ClassA's factory method does, except return a ClassB.

class ClassA{
   static public function Factory($construct_args, $contents){
      $new = new ClassA($construct_args);
      //Does lots of stuff with $contents
   }
}

class ClassB extends ClassA{
   //specialty methods and properties
}

echo get_class(ClassB::Factory($construct_args, $contents);

This should echo ClassB

Is there a way I can use ClassA's Factory Method without copy-pasting it to ClassB? I am using PHP5, but not 5.3.0.

A: 

I guess this is a case of Late Static Binding. If you are not on 5.3, you have to copy it.

However, you could also remove the factory method from ClassA and make it into a dedicated Factory or Builder class that knows how to create ClassA and any special classes instead.

Gordon
A: 

In PHP 5.3, it's just a matter of doing (see late static bindings):

static public function Factory($construct_args, $contents){
   $new = new static($construct_args);
   //Does lots of stuff with $contents
   return $new;
}

In PHP 5.2, you have to be more creative. Something like:

class ClassA {
   static function Factory($construct_args, $contents) {
       return self::privFactory($construct_args, $contents, "ClassA");
   }
   static protected function privFactory($construct_args, $contents, $type){
      $new = new $type($construct_args);
      //Does lots of stuff with $contents
      return $new;
   }
}

class ClassB extends ClassA{
   static function Factory($construct_args, $contents) {
       return self::privFactory($construct_args, $contents, "ClassB");
   }
}
Artefacto
I'm aware, but as stated, don't have 5.3.0
Tyson of the Northwest
+1  A: 

The do exactly what you want you need Late Static Binding, so you need PHP 5.3. It can not be done as you want in PHP 5.2. People have tried.

The work arounds I've seen/used for 5.2 are

  1. As you mentioned (and don't want to do) copy your factory method into each class

  2. Require end-users of the factory to supply the name of the class they're instantiating as an argument

  3. Require your factories to implement an interface or have them inherit from an abstract class (or just know the convention) that requires the definition of a static "getClassName" method, which will be used in the factory. This is similar to number one, but some people prefer it as it allows their factory method to remain in the "bottom" class.

Alan Storm