假设我们有一个父类和一个子类。父类检查一些参数,并决定子类更适合处理给定的请求-是否有方法将现有(父)对象重新创建为父对象所在的子类的对象?
父类示例:
/**
* 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图案。通过这种方式,您可以使用一个静态方法来获取配置字符串和现有的汽车,并返回用与配置匹配的功能装饰的给定汽车。这让你可以更灵活地处理所有的利弊(你可以在拖拉机上有一个遮阳棚)。