覆盖工厂方法:如何返回子类对象类型?

时间:2012-05-16 11:04:42

标签: php oop inheritance override factory-pattern

假设我在PHP中有一个父类,如下所示:

class A {

    private $property;

    public static function factory($arg) {
        $object = new A();
        $object->property = $arg;
        return $object;
    }

}

我想以这种方式扩展它:

class B extends A {

    public static function factory() {
        return parent::factory('constant');
    }

}

当我B::factory()时,我得到了A类型的对象。如果我想要B类型的对象怎么办? 我无法更改课程A 的代码中的任何内容。

2 个答案:

答案 0 :(得分:1)

第一版

那是因为你在工厂方法中对A类进行了硬编码 在课程A中,而不是$object = new A()尝试(需要Php 5.3):

$class_name = get_called_class();
$object = new $class_name;

get_called_class()“获取调用静态方法的类的名称。”

更短的版本:

$object = new static();

第二版(硬编码父类):

手动复制对象属性:

$parent = parent::factory($args);
$obj = new static();
$obj->setTimestamp($parent->getTimestamp());
$obj->setTimezone($parent->getTimezone());
return $obj;

或使用黑客自动执行此操作:

  

How to Cast Objects in PHP

答案 1 :(得分:0)

在你的例子中:

  1. 你有两个课程(至少)
  2. 这两个类都可以实例化(具体,不纯粹或抽象)
  3. 一个类是另一个类的超类
  4. 这两个类都使用“工厂”方法实例化
  5. 子类的“factory”方法可以调用超类的“factory”方法
  6. 每个“工厂”方法可以有多种类型或数量的参数
  7. <强>问题

    现在,这引起了我的注意:

    class B extends A {
    
        public static function factory() {
            return parent::factory('constant');
        }
    
    }
    

    短&amp;快速回答:

    将其更改为:

    class B extends A {
    
        public static function factory() {
            return A::factory('constant');
        }
    
    }
    

    长期无聊的时髦延伸回答:

    您正在尝试覆盖(并使用不同参数重载)静态函数。

    这是一个常见的错误,假设静态方法是虚拟的,可以被覆盖。有些编程语言允许(Object Pascal,Delphi),其他编程语言(C#,Java),PHP依赖于版本,我认为。

    老实说,“静态函数”的工作方式类似于具有命名空间的全局函数,它具有对类的所有成员的公共访问权限,而不是方法。我建议将它们视为全局函数。

    干杯。