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

3

8

I have a subclass that needs to return a subclass of the return type of its parent class. I believe this is called a covariant return type. I am wondering the simplest way to convert from the parent to the child class.

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 ?
  }
}
Timepleaser answered 19/8, 2011 at 15:9 Comment(0)
T
8

In PHP you can not "convert" objects from type/class A to B with a feature available in the language.

You can do so however by making use of serialization if your objects support it (normally plain old PHP objects do support serialization). In the serailized form you change the class of the object and unserialize it again. A has turned into B then. But that's not really fluent.

Tzar answered 19/8, 2011 at 15:12 Comment(0)
N
3

This actually should be a comment, but I'm going to make an important point.

Programming is engineering and programming is design. There's no way to tell why design A is better than design B without knowing how it's going to be used. Ask a designer, should your submit button be red or green - and she says: hmm, where, on which site? Ask an engineer if you should use a beam or a gear couping - and the answer will be: depends on what for. So, what makes you think we can give you a meaningful design advice, if you only gave us a "BrokenCar" class with a "foo" method. Tell us what you actually want to achieve with that, otherwise the only answer I can come up with is

the best way to use foo is bar

Noctambulous answered 19/8, 2011 at 15:22 Comment(1)
Sorry for the vague example... I tried to simplify what I was doing perhaps too much. I meant to illustrate that 'B' provides extra methods that do not exist in 'A'. 'B' also overrides some methods from 'A' in my actual code. I could duplicate the logic in the overridden methods and then just quit calling the parent 'foo' method at all, but that was a lot of duplication.Timepleaser
H
2

As hakre stated, casting to user defined types is not natively possible in PHP (as far as I know).

What you could do is create a method in either class A or B. Something like:

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

or

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

In the first example the first factory method can be problematic, since it requires A to have concrete knowledge about a specific subclass. You need to determine whether this is desirable in your situation. Perhaps you could abstract this to have the factory method accept any object that inherits from A, like the second factory method.

In the second example, B automatically already knows about A, because it inherits from it. This might be more desirable. But come to think of it, this could even already be implemented in A as well, such that the method is automatically available in all subclasses of A already.

Henrietta answered 19/8, 2011 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.