是否可以在具有共同父级的类之间进行转换?

时间:2009-10-21 16:27:22

标签: php object

如果我有两个类,每个类都扩展了一个共同的父级,是否可以在它们之间进行转换?

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';

以此代码为例,我想将$fooFooDatabase的实例转换为FooFlatfile,同时保留属性bar的值。

编辑:我确实意识到实际上这样做在实践中并不是一个好主意。相反,我遇到了这种情况,这是一个潜在的解决方案,并对如何实现它感到好奇。

3 个答案:

答案 0 :(得分:2)

虽然不建议,但这是可能的。看看A dark corner of PHP: class casting。基本上是:

  1. 序列化课程;
  2. 更改序列化表格中的班级名称;然后
  3. 反序列化。
  4. 是的,这是一个黑客攻击。

    更大的问题:你为什么要这样做?如果您需要更改类,则表明您的对象模型很糟糕。它让我想起他们曾经给出的介绍性OO的旧例子:

    • 人员类;
    • 推销员延伸人;
    • 经理人延伸人。

    这是一个可怕的示例,出于同样的原因:如果有人从推销员变为经理人怎么办?将其与基于组合的方法进行比较,其中Person 具有作业(其中Manager和Salesman是Job的实例或子类)。更多声音方法。

    最后,我要补充一点,如果你无法改变某些代码迫使你这样做,你最好使用某种适配器或外观:

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

    同样,这比任何类型的自动属性复制类更改过程都要好得多。

答案 1 :(得分:1)

您可以通过创建新的并复制值来完成所需的工作吗?

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

如果没有完成您的需要,请提供更多详细信息。

对评论的回应:

如果您计划经常这样做,那么创建一个成员函数以返回某种数组或结构中的所有成员将很容易。然而,在那一点上,你真的需要问自己“为什么我这样做?”另一个响应者现场说,如果你经常想要这样做,你已经非常糟糕地设计了你的课程。

如果您有两个课程,您想要在两个课程之间切换,请删除将它们分开的内容,然后创建一个课程。要么它们基本上是相同的,在这种情况下你可以在它们之间切换,但通过只做一个课你会更好。

或者它们彼此根本不同,在这种情况下你仍然需要两个类。如果您有一个数据库,并且您正在尝试将其转换为平面文件,则需要使用导出功能将数据库转换为平面数据。动态更改类就像使用记事本打开Oracle文件一样:它不会以有意义的,可用的方式产生数据。要介于它们之间,您可以编写使用相同数据结构的“导出”和“导入”功能。您创建一个新的,从旧导出,导入到新,并删除旧。

我坦率地说不知道还有什么可说的,因为我无法想象这样做会有意义的场景。如果您可以提供有关您尝试解决的背景的更多详细信息,我可以提供更好的建议。

答案 2 :(得分:1)

你可以做这样的事情,有一些限制(限制构造函数的类型,不能复制私有变量),但它可以使它工作。

class Foo {
  public $bar;

  protected function convertTo($classname) {
    $rc_other_class = new ReflectionClass($classname);
    if ($rc_other_class->isSubclassOf(get_class())) {
      // there's a limitation here in that the constructor can't take params
      $other_class = new $classname();
      $rc_this_class = new ReflectionClass(get_class());
      $properties = $rc_this_class->getProperties();
      foreach ($properties as $property) {
        if (!$property->isStatic() &&
            $property->getDeclaringClass()->getName() == get_class()) {
          $property = $property->getName();
          if (property_exists($this, $property)) {
            // this will throw if you try to copy a private var, add a filter to
            // getProperties to prevent this but you probably want the error
            $other_class->$property = $this->$property;
          }
        }
      }
    } else {
      return false;
    }
  }
}