tags:

views:

53

answers:

2

If I have two classes that each extend a common parent, is it possible to convert between them?

class Foo
{

    public $bar;


}

class FooDatabase extends Foo
{

    public function load() {}

    public function save() {}

}

class FooFlatfile extends Foo
{

    public function load() {}

    public function save() {}

}

$foo = new FooDatabase;
$foo->bar = 'elf';

Using this code as an example, I want to convert $foo from an instance of FooDatabase to FooFlatfile, while retaining the value of the property bar.

Edit: I do realise that actually doing this isn't such a great idea in practice. Rather, I came across a situation in which this was a potential fix, and became curious about how it might be achieved.

+2  A: 

This is possible although not advised. Take a look at A dark corner of PHP: class casting. Basically:

  1. Serialize the class;
  2. Change the class name in the serialized form; then
  3. Deserialize it.

Yes, it's a hack.

The bigger question: is why do you want to do this? If you have the need to change class it's a very strong indicator that your object model is bad. It reminds me of the old examples of introductory OO they used to give:

  • Person class;
  • Salesman extends Person;
  • Manager extends Person.

which is a horrible example for the same reason: what if someone changes from a Salesman to a Manager? Compare that to the composition-based approach where Person has-a Job (where Manager and Salesman are instances or subclasses of Job). Much more sound approach.

Lastly, I'll add that if some code you can't change is forcing you to do this, you'd be best off using some sort of adapter or facade:

class A { ... }
class B {
  public function asA() {
    $ret = new A;
    // configure;
    return $ret;
  }
  ...
}

Again this is much more sound than any sort of automatic property copying class changing process.

cletus
Some interesting points, thank-you.
etheros
+1  A: 

Can you accomplish what you need by creating a new one and copying the values over?

$foo2 = new FooFlatFile;
$foo2 = foo->bar;

If doesn't get done what you need, please give us more details.

Response to comment:

If you are planning on doing that often, it would be easy to create a member function to return all members in some sort of array or struct. However, at that point, you really need to ask yourself "why am I doing this?" The other responder is spot on in saying that if you are regularly wanting to do this, you have designed your classes very badly.

If you've got two classes you are wanting to switch between, remove what is separating them, and make one class. Either they are fundamentally the same, in which case you could get away with switching between them, but you would be far better served by making just one class.

Or they are fundamentally different from each other, in which case you still need two classes. If you have a database, and you're trying to turn it into a flat file, you need to have an export function translate the database into flat data. Dynamically changing classes would be like using Notepad to open up an Oracle file: it would not yield the data in a meaningful, usable manner. To go between them, you write 'export' and 'import' functions that use the same data structure as each other. You create a new one, export from the old, import into the new, and delete the old.

I'm frankly not sure what else to say, because I can't imagine a scenario where it would make sense to do this. If you could give more details about the background of what you're trying to solve, I could offer better advice.

David Oneill
That is the simplest solution, but what if there are many properties? Is there some automated way to do this?
etheros
Edited answer regarding your comment.
David Oneill
Some more interesting points, thank-you for the response
etheros