代码之家  ›  专栏  ›  技术社区  ›  etheros

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

  •  0
  • etheros  · 技术社区  · 17 年前

    如果我有两个类,每个类都扩展了一个公共父类,那么可以在它们之间进行转换吗?

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

    以这段代码为例,我想转换 $foo FooDatabase 到 FooFlatfile bar .

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

    3 回复  |  直到 17 年前
        1
  •  2
  •   cletus    17 年前

    这是可能的,但不建议这样做。看看 A dark corner of PHP: class casting

    1. 序列化类;
    2. 反序列化它。

    是的,这是一个黑客。

    更大的问题是:你为什么要这样做?如果您需要更改类,这是一个很强的指标,表明您的对象模型不好。这让我想起了他们曾经给出的介绍性OO的老例子:

    • 人员类别;

    哪一个是 极坏的 有一个 作业(其中经理和销售人员是作业的实例或子类)。更合理的方法。

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

    同样,这比任何类型的自动属性复制类更改过程都更合理。

        2
  •  1
  •   David Oneill    17 年前

    你能通过创建一个新的并复制这些值来完成你需要的吗?

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

    对评论的答复:

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

    如果您有两个类要在它们之间切换,请删除分隔它们的内容,然后创建一个类。或者它们基本相同,在这种情况下,您可以在它们之间切换,但只创建一个类会更好。

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

        3
  •  1
  •   Brian Steadman    15 年前

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

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