在 PHP 中,无法进行强制转换来更改对象的类型(不使用令人讨厌的扩展名)。实例化对象后,您将无法再更改类(或其他实现详细信息)...
您可以使用如下方法模拟它:
public function castAs($newClass) {
$obj = new $newClass;
foreach (get_object_vars($this) as $key => $name) {
$obj->$key = $name;
}
return $obj;
}
用法:
$obj = new MyClass();
$obj->foo = 'bar';
$newObj = $obj->castAs('myChildClass');
echo $newObj->foo; // bar
但请注意,它实际上并没有改变原始类。它只是创建一个新的。请注意,这需要属性是公开的,或者具有getter和setter魔术方法......
如果你想要更多的检查(我建议这样做),我会添加以下行作为第一行,以防止出现问题:castAs
if (!$newClass instanceof self) {
throw new InvalidArgumentException(
'Can\'t change class hierarchy, you must cast to a child class'
);
}
好吧,既然Gordon发布了一个非常黑魔法的解决方案,我将做同样的事情(使用RunKit PECL扩展(警告:这里是龙):
class myClass {}
class myChildClass extends MyClass {}
function getInstance($classname) {
//create random classname
$tmpclass = 'inheritableClass'.rand(0,9);
while (class_exists($tmpclass))
$tmpclass .= rand(0,9);
$code = 'class '.$tmpclass.' extends '.$classname.' {}';
eval($code);
return new $tmpclass();
}
function castAs($obj, $class) {
$classname = get_class($obj);
if (stripos($classname, 'inheritableClass') !== 0)
throw new InvalidArgumentException(
'Class is not castable'
);
runkit_class_emancipate($classname);
runkit_class_adopt($classname, $class);
}
所以,与其做 ,不如做这样的事情:new Foo
$obj = getInstance('MyClass');
echo $obj instanceof MyChildClass; //false
castAs($obj, 'myChildClass');
echo $obj instanceof MyChildClass; //true
从类内部(只要它是用以下方式创建的):getInstance
echo $this instanceof MyChildClass; //false
castAs($this, 'myChildClass');
echo $this instanceof MyChildClass; //true
免责声明:请勿执行此操作。真的,不要。这是可能的,但这是一个如此可怕的想法...