1

假设我在 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怎么办?我无法更改 class 代码中的任何内容A

4

2 回答 2

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;

或使用 hack 自动执行此操作:

如何在 PHP 中转换对象

于 2012-05-16T11:07:21.247 回答
0

在您的示例中:

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

问题

现在,这就是它引起我注意的地方:

class B extends A {

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

}

简短快速的回答:

将其更改为:

class B extends A {

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

}

无聊的潮人扩展答案:

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

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

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

干杯。

于 2012-05-16T17:51:55.927 回答