如果我有一个扩展类Bar的类Foo和一个Bar实例,那么无论如何都要使用Bar的实例来“填充”一个新的Foo实例?
基本上,我只能检索Bar,但我想在我的代码中使用Foo,因为它为我提供了许多其他方法。
我看到很多解决方案遇到了类似的问题,但它们似乎都是python或c#。
我无法使用ReflectionClass :: newInstanceArgs,因为我无法访问进入Bar构造函数的数据以便首先创建它。
答案 0 :(得分:2)
实现此目标的推荐方法是dependency injection。 Foo
的构造函数可以接受Bar
的实例,然后您必须编写代码以从Foo
对象加载新Bar
对象的状态
如果PHP的功能完全符合您的描述,则会产生问题,因为即使Foo
扩展Bar
,这两个类仍然可能非常不同。我不知道PHP如何足够聪明,知道如何自动将一个类的实例转换为另一个类的实例。
话虽如此,在正确的情况下,下面的(非常hacky)“解决方案”可以做你所描述的。我不建议实际使用它。我主要是想表明你不得不求助于一些奇怪的事情来做这件事。
function convertObject($object, $newClass)
{
return unserialize(
preg_replace(
'/^O\:\d+\:"[^"]+"/',
'O:'.strlen($newClass).':"'.$newClass.'"',
serialize($object)
)
);
}
答案 1 :(得分:1)
没有内置方法可以轻松完成您想要的任务。必须重新设计这些类的接口。也许是这样的事情:
<?php
class Bar
{
...
}
class Foo extends Bar
{
public static function fromBar(Bar $bar)
{
$foo = new self();
... (copy data here) ...
return $foo;
}
}
答案 2 :(得分:0)
我刚写了一些这样的例子是为了扩展自定义驱动程序,可能需要额外的支持包用于上述核心驱动程序文件。
// File: parent.php
class parent_class() {
protected $_protected_object; // set in constructor
protected $_protected_var = "Something dynamic";
public function __construct() {
// keep in mind that if you don't override this constructor, this will execute when extended
}
public function create_resource() {
$this->_protected_object = new SomeObjectInstance();
}
public function child_class() {
static $child = null;
if (is_null($child)) {
$file = "child.php";
if (!\file_exists($file)) {
throw new Exception("Couldn't load '$file', doesn't exist");
} else {
require_once($file);
$child = new child_class();
$child->__overload("_protected_object", $this->_protected_object)->__overload("_protected_var", $this->_protected_var);
}
}
return $child;
}
}
// File: child.php
class child_class extends parent_class {
protected function __overload($index, &$value) {
$this->$index =& $value;
return $this;
}
public function __construct() {
// REMEMBER: if you don't declare this method, the parent's constructor will execute
}
public function extended_func() {
// code
}
public function etc() {
// code
}
}
// Code instantiating objects:
$parent = new parent_class();
$parent->create_resource();
var_dump($parent);
/**
* Would output something like this:
*
* object(parent_class)#1 (2) {
* ["_protected_object":protected]=>
* object(SomeObjectInstance)#2 (*) {
* %OBJECT PROPERTIES%
* }
* ["_protected_var":protected]=>
* string(17) "Something dynamic"
* }
*/
$child = $parent->child_class();
var_dump($child);
/**
* Would output something like this:
*
* object(child_class)#3 (2) {
* ["_protected_object":protected]=>
* &object(SomeObjectInstance)#2 (*) {
* %OBJECT PROPERTIES%
* }
* ["_protected_var":protected]=>
* &string(17) "Something dynamic"
* }
*/
请注意,$ child的第二个var_dump()输出与$ parent相同的信息,但您现在可以看到所述属性前面带有&符号(&amp;),表示现在有引用。因此,如果您在父类实例中更改了有关这两个属性的任何内容,它将反映在子类实例中。