将对象转换为其子类之一(协变返回类型)的正确OO方式是什么?


What is the proper OO way to convert an object to one of its subclasses (covariant return type)?

我有一个子类,它需要返回父类返回类型的子类。我相信这叫做协变返回类型。我想知道从父类转换到子类的最简单的方法。

class A {
}
class B extends A {
  function bar() {
  }
}
class Car {
  function foo() {
    return new A();
  }
}
class BrokenCar extends Car {
  function foo() {
    $a = parent::foo();
    //What is the cleanest way to convert $a to type B ?
  }
}

在PHP中,您不能使用该语言中可用的特性将对象从类型/类A "转换"到B。

如果你的对象支持序列化,你可以通过使用序列化来实现(通常普通的老式PHP对象确实支持序列化)。在序列化形式中,您更改对象的类并再次反序列化它。A变成了B。但这不是很流畅

这实际上应该是一个注释,但我要强调一点。

编程是工程,编程是设计。在不知道如何使用的情况下,没有办法说明为什么设计A比设计B更好。问一个设计师,你的提交按钮应该是红色还是绿色,她说:嗯,在哪里,在哪个网站上?如果你问工程师应该使用横梁还是齿轮联轴器,答案将是:这取决于你的用途。那么,是什么让你认为我们可以给你一个有意义的设计建议,如果你只是给我们一个"破碎的";类与"foo"方法。告诉我们你真正想要实现什么,否则我唯一能想到的答案就是

使用foo的最佳方式是bar

正如hakre所说,在PHP中,转换为用户定义的类型是不可能的(据我所知)。

你可以在类a或类b中创建一个方法,比如:

class A
{
    public static function fromB( B $object )
    {
        /* your routine to convert an object of class B to an instance of class A */
    }
    /* or */
    public static function fromA( A $object )
    {
        /* your routine to convert any object that is a subclass of A to a concrete instance of class A */
    }
}

class B
    extends A
{
    // this method could even be implemented in A already as well actually
    public function toA()
    {
        /* your routine to convert this object to an object of class A */
    }
}

在第一个例子中,第一个工厂方法可能有问题,因为它要求A具有关于特定子类的具体知识。您需要确定这在您的情况下是否可取。也许您可以将其抽象为让工厂方法接受从A继承的任何对象,就像第二个工厂方法一样。

在第二个例子中,B自动已经知道了A,因为它继承了它。这可能更可取。但是仔细想想,这甚至可能已经在A中实现了,这样该方法就可以在A的所有子类中自动使用。