假设我在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
代码中的任何内容。
第一个版本
这是因为您在工厂方法中对 A
类进行了硬编码。
在类 A
中,而不是尝试$object = new A()
(需要 Php 5.3(:
$class_name = get_called_class();
$object = new $class_name;
get_called_class()
"获取调用静态方法的类的名称"。
较短的版本:
$object = new static();
第 2 版(硬编码父类(:
手动复制对象属性:
$parent = parent::factory($args);
$obj = new static();
$obj->setTimestamp($parent->getTimestamp());
$obj->setTimezone($parent->getTimezone());
return $obj;
或者使用黑客自动完成:
如何在 PHP 中强制转换对象
在您的示例中:
- 您有两个类(至少(
- 这两个类都可以实例化(具体,不是纯类或抽象类(
- 一个类是另一个类的超类
- 这两个类都使用"工厂"方法实例化 子类的"工厂"方法
- 可以调用超类的"工厂"方法
- 每个"工厂"方法可以有多种类型或参数计数
问题
现在,这就是它引起我注意的:
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取决于版本。
老实说,"静态函数"的工作方式类似于具有命名空间的全局函数,它们对类的所有成员具有公共访问权限,而不是方法。我建议始终将它们视为全局函数。
干杯。