一个对象“;进化”;转换为其中一个的对象';s的儿童班


Can a object "evolve" into an object of one of it's child classes?

假设我们有一个父类和一个子类。父类检查一些参数,并决定子类更适合处理给定的请求-是否有方法将现有(父)对象重新创建为父对象所在的子类的对象?

父类示例:

/**
 * 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

子类示例:

/**
 * SUV car
 */
class suv extends car {
    /**
     * Add 4x4 drive
     */
    protected function add4x4() {
        // (...)
    } // add4x4
} // suv

现在,获得suv对象最明显的方法是从一开始就直接创建它:

$car = new suv();
$car->configure($config);

挑战在于,我不知道创建对象时需要car还是suv对象;在$car->configure()方法中解析之前,我不知道$config字符串包含哪些选项(该字符串可以来自任何地方,例如用户输入)。

一个简单的解决方法是在创建任何对象之前,将configure方法从car中移出以分析字符串-然而,它在逻辑上属于car对象,所以我真的想把它保留在那里:)

有办法解决这个难题吗?如果没有,你会建议什么是"最干净"的解决方法?

提前感谢!

编辑:

正如前面所指出的,我的问题与此问题非常相似:将当前对象($this)强制转换为派生类答案是,这在技术上是可能的,但不应该这样做。然而,还没有提出一个令人信服的替代方案(有人建议使用工厂,但我觉得这只会解决部分问题)。

正如注释中所说,最常见的方法是使用一个静态方法,将字符串作为参数并返回正确的实例。通过这种方式,您可以将方法保留在car类中,正如您所说,这是最合乎逻辑的。

顺便说一句,如果它更多的是在现有对象上添加功能。你可以考虑Decorator图案。通过这种方式,您可以使用一个静态方法来获取配置字符串和现有的汽车,并返回用与配置匹配的功能装饰的给定汽车。这让你可以更灵活地处理所有的利弊(你可以在拖拉机上有一个遮阳棚)。