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).
As said in comments, the most common way to do what you want would be to have a static method taking the string as parameter and returning the correct instance. This way, you would keep the method inside the car class which is, as you said, is the most logical.
By the way, if it is more about adding features on an existing object. You might consider the Decorator pattern. This way, you could have a static method taking the configuration string and the existing car and returning given car decorated with the features matching the configuration. This allows you to be more flexible with all the pros and cons (you could have a sun roof on a Tractor).