如果我有一個擴展類Bar和Bar實例的Foo類,那麼無論如何要使用該Bar實例來「填充」一個Foo的新實例?基本上,我只能檢索Bar,但我想在我的代碼中使用Foo,因爲它給了我很多其他方法。在PHP中,從基類實例創建擴展類的對象
我看到不少解決方案都出現類似的問題,但它們都似乎是python或c#。
我無法使用ReflectionClass :: newInstanceArgs,因爲我不能訪問進入Bar構造函數的數據以便首先創建它。
如果我有一個擴展類Bar和Bar實例的Foo類,那麼無論如何要使用該Bar實例來「填充」一個Foo的新實例?基本上,我只能檢索Bar,但我想在我的代碼中使用Foo,因爲它給了我很多其他方法。在PHP中,從基類實例創建擴展類的對象
我看到不少解決方案都出現類似的問題,但它們都似乎是python或c#。
我無法使用ReflectionClass :: newInstanceArgs,因爲我不能訪問進入Bar構造函數的數據以便首先創建它。
有沒有內置的方法可以輕鬆地做你想做的。這些類的接口必須重新設計一點。也許是這樣的:
<?php
class Bar
{
...
}
class Foo extends Bar
{
public static function fromBar(Bar $bar)
{
$foo = new self();
... (copy data here) ...
return $foo;
}
}
謝謝。是的,意識到根據我的問題期望能夠做到這是不合理的,我想我會按照這些方式做一些事情。可能會放棄'擴展',並將Bar作爲Foo的一個屬性。 – petesiss
推薦的方法是通過dependency injection。您的Foo
的構造函數可以接受Bar
的實例,然後您必須編寫代碼以加載Bar
對象中新對象Foo
的狀態。
如果PHP具有完全符合您所描述的功能,則會出現問題,因爲即使Foo
擴展了Bar
,這兩個類仍然可能會有很大的不同。我沒有看到PHP如何聰明地知道如何自動將一個類的實例轉換爲另一個類的實例。這樣說,在正確的情況下,下面的(非常冒險的)「解決方案」可以做你所描述的。我不會推薦實際使用它。我主要只是想表明,你不得不訴諸一些奇怪的東西來做到這一點。
function convertObject($object, $newClass)
{
return unserialize(
preg_replace(
'/^O\:\d+\:"[^"]+"/',
'O:'.strlen($newClass).':"'.$newClass.'"',
serialize($object)
)
);
}
是的...我不會那樣做convertObject。我想在這種情況下,考慮到我們的目的是爲擴展對象提供一個合適的初始狀態,基類的屬性似乎並不是那麼神奇......但當然並非總是如此。我想我會去讓Bar成爲Foo的一個財產。 – petesiss
我剛寫的東西這個例子中,用於擴展可能需要對上述核心驅動程序文件的附加支持包(S)定製驅動程序基礎上的。
// 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"
* }
*/
注意,第二的var_dump()爲$子輸出相同的信息$父,但你可以看到現在說屬性的前面有符號(&),表示現在有引用。因此,如果您在父類實例中更改了有關這兩個屬性的任何內容,它將反映在子類實例中。
你可能會寫一個Foo的函數/構造函數,它帶了一個Bar實例並填充了Foo實例 – gunnx
你爲什麼要這樣做?這聽起來像是有陰險的事情.. –
我不認爲你可以在PHP中投射自定義對象。也許你可能會在[這篇文章](http://stackoverflow.com/a/2232065/1028949)中找到一些有用的信息。 – Quantastical