Assume we have a parent class and a child class. The parent class checks some parameters and decides that the child class would be better suited to handle the given request - is there a way to recreate the existing (parent)-object as an object of the child class from whithin the parent object?
Example of a parent class:
/**
* Simple car
*/
class car {
/**
* The constructor
*/
public function __construct() {
// (...)
}
/**
* Add a sunroof to the car
*/
protected function addSunRoof() {
// (...)
}
/**
* Parse a config string and configure the car accordingly
* @param string $config
*/
public function configure($config) {
$options = explode(";", $config);
// Do something for every option in $config string
foreach ($options as $o) {
switch ($o) {
case "sunroof" :
$this->addSunRoof();
break;
case "4x4" :
// 'car' does not have support for '4x4', but the child class 'suv' does
// -> This 'car' object should therefore 'evolve' and become a 'suv' object - how?
case "foo" :
// (...)
} // switch
} // foreach
} // configure
} // car
Example of the child class:
/**
* SUV car
*/
class suv extends car {
/**
* Add 4x4 drive
*/
protected function add4x4() {
// (...)
} // add4x4
} // suv
Now, the most obvious way to get a suv
object would be to create it directly from the beginning:
$car = new suv();
$car->configure($config);
The challenge is that I don't know whether a car
or a suv
object is required when creating the object; I don't know what options the $config
string contains until it gets parsed in the $car->configure()
method (The string can come from anywhere, e.g. user input).
A simple workaround would be to move the configure
method out of car
to analyse the string before creating any object - however, it logically belongs to the car
object, so I would really like to keep it there :)
Is there a way to solve this puzzle? If not, what would you suggest as the "cleanest" workaround?
Thanks in advance!
Edit:
As it was pointed out, my question is very similar to this one: Cast the current object ($this) to a descendent class The answers there are saying that it's technically possible, but should not be done. However, a convincing alternative has not been suggested yet (It has been suggested to use factories, but I feel this would only solve a part of the problem).