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

时间:2011-08-19 15:09:12

标签: php oop covariant

我有一个子类需要返回其父类的返回类型的子类。我相信这被称为协变返回类型。我想知道从父类转换到子类的最简单方法。

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 ?
  }
}

3 个答案:

答案 0 :(得分:8)

在PHP中,您不能使用该语言中提供的功能将对象从类型/类A“转换”为B.

但是,如果对象支持序列化,则可以使用序列化(通常普通的旧PHP对象支持序列化)。在serailized形式中,您可以更改对象的类并再次对其进行反序列化。 A然后变成了B.但那不是很流利。

答案 1 :(得分:3)

这实际上应该是一个评论,但我会提出一个重点。

编程是工程和编程的设计。没有办法告诉为什么设计A比设计B更好而不知道它将如何被使用。询问设计师,如果你的提交按钮是红色或绿色 - 她说:嗯,哪里,在哪个网站?询问工程师是否应该使用梁或齿轮 - 并且答案将是:取决于为什么。那么,是什么让你认为我们可以给你一个有意义的设计建议,如果你只给我们一个带有“foo”方法的“BrokenCar”类。告诉我们你真正想要实现的目标,否则我能想出的唯一答案是

使用foo的最佳方式是bar

答案 2 :(得分:2)

正如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 */
    }
}

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

在第二个例子中,B自动已经知道A,因为它继承了它。这可能更合乎需要。但是考虑到这一点,这甚至可以在A中实现,这样该方法就可以在A的所有子类中自动使用。