Приведение к изменению типа объекта в 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
Но учтите, что на самом деле это не меняет первоначальный класс. Это просто создает новый. И помните, что для этого необходимо, чтобы свойства были общедоступными или имели магические методы получения и установки ...
И если бы вы хотели еще несколько проверок (я бы предложил), я бы добавил эту строку в качестве первой строки castAs
, чтобы предотвратить проблемы:
if (!$newClass instanceof self) {
throw new InvalidArgumentException(
'Can\'t change class hierarchy, you must cast to a child class'
);
}
Хорошо, поскольку Гордон опубликовал очень черное магическое решение, я сделаю то же самое (используя расширение 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
Отказ от ответственности: не делайте этого. На самом деле нет. Это возможно, но это такая ужасная идея ...