Каков правильный ОО-способ для преобразования объекта в один из его подклассов (ковариантный тип возвращаемого значения)? - PullRequest
8 голосов
/ 19 августа 2011

У меня есть подкласс, который должен возвращать подкласс типа возврата его родительского класса.Я считаю, что это называется ковариантным типом возврата.Мне интересно самый простой способ преобразования из родительского в дочерний класс.

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 ]

8 голосов
/ 19 августа 2011

В PHP вы не можете "преобразовывать" объекты из типа / класса A в B с помощью функции, доступной на языке.

Однако вы можете сделать это, используя сериализацию, если ваши объекты поддерживают ее (обычнопростые старые объекты PHP поддерживают сериализацию).В serailized форме вы меняете класс объекта и снова его сериализуете.А превратился в Б тогда.Но это не совсем свободно.

3 голосов
/ 19 августа 2011

На самом деле это должен быть комментарий, но я собираюсь сделать важное замечание.

Программирование - это разработка, а программирование - это дизайн. Невозможно сказать, почему дизайн A лучше, чем дизайн B, не зная, как он будет использоваться. Спросите дизайнера, должна ли ваша кнопка отправки быть красной или зеленой - и она говорит: хм, где, на каком сайте? Спросите инженера, следует ли вам использовать балку или зубчатое соединение - и ответ будет: зависит от того, для чего. Итак, что заставляет вас думать, что мы можем дать вам полезный совет по дизайну, если вы только дали нам класс "BrokenCar" с методом "foo". Скажите нам, чего вы на самом деле хотите достичь, в противном случае единственный ответ, который я могу придумать -

лучший способ использовать foo - это бар

2 голосов
/ 19 августа 2011

Как указано 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.

...