在 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 扩展(警告:这里是 dragons):
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
免责声明:不要这样做。真的,不要。这是可能的,但这是一个可怕的想法......