【问题标题】:How to handle nested (recursive iterator) dynamics objects in PHP?如何在 PHP 中处理嵌套(递归迭代器)动态对象?
【发布时间】:2016-05-31 17:05:12
【问题描述】:

我有一个 foreach 实例化了几种类,它必须是嵌套的。它们都扩展了同一个抽象类。

我不需要处理任何具体案例,而是所有案例。

我应该如何处理这种嵌套?我正在考虑在执行 foreach 的类中定义一个函数,或者在 Parent 类中定义一个函数,其中定义了所有这些情况。

示例 1

<?php
class Parent
{
    private $childs = [];
    function nest($child)
    {
        $this->childs[] = $child;
    }
}

// There is different types of A that are nested according to its type.
$A1 = class A extends Parent { $type = 1 }
$A2 = class A extends Parent { $type = 2 }
$B = class B extends Parent {}
$A3 = class A extends Parent { $type = 2 }
$C = class C extends Parent {}

// foreach ([$A1, $A2, $B, $A3, $C])
// $A1->nest($A2);

但是$A1不能嵌套,$A2只能被$A1嵌套,$B可以被$A1$A2嵌套但是应该被$A2嵌套,因为它是前一个对象可以嵌套的,$A3应该嵌套到$A1等等

// expected output of the example
object(A)#1 (2) {
  ["type"]=>
  int(1)
  ["childs":"Parent":private]=>
  array(2) {
    [0]=>
    object(A)#2 (2) {
      ["type"]=>
      int(2)
      ["childs":"Parent":private]=>
      array(1) {
        [0]=>
        object(B)#3 (2) {
          ["childs":"Parent":private]=>
          array(0) {
          }
        }
      }
    }
    [1]=>
    object(A)#4 (2) {
      ["type"]=>
      int(2)
      ["childs":"Parent":private]=>
      array(1) {
        [0]=>
        object(C)#5 (1) {
          ["childs":"Parent":private]=>
          array(0) {
          }
        }
      }
    }
  }
}

示例 2

<?php
$numbers = [1, 2, 3, 2, 4];

class Number
{
    private $biggers = [];
    public function addBigger($number)
    {
        $this->biggers[] = $number;
    }
}

class One extends Number{ private $value = 1; }
class Two extends Number{ private $value = 2; }
class Three extends Number{ private $value = 3; }
class Four extends Number{ private $value = 4; }

foreach ($numbers as $number) {
    // Algorithm
}

预期输出:

object(One)#1 (2) {
["value":"One":private]=>
  int(1)
  ["biggers":"Number":private]=>
  array(2) {
    [0]=>
    object(Two)#2 (2) {
    ["value":"Two":private]=>
      int(2)
      ["biggers":"Number":private]=>
      array(1) {
        [0]=>
        object(Three)#3 (2) {
        ["value":"Three":private]=>
          int(3)
          ["biggers":"Number":private]=>
          array(0) {
          }
        }
      }
    }
    [1]=>
    object(Two)#4 (2) {
    ["value":"Two":private]=>
      int(2)
      ["biggers":"Number":private]=>
      array(1) {
    [0]=>
        object(Four)#5 (2) {
        ["value":"Four":private]=>
          int(4)
          ["biggers":"Number":private]=>
          array(0) {
          }
        }
      }
    }
  }
}

【问题讨论】:

  • 嵌套到底是什么意思?
  • 也不明白.. 会嵌套谁和什么?嵌套在视觉上看起来如何? $type 代表什么?想要完成什么?
  • 为了清楚起见,我添加了父定义
  • 澄清一下,你期望什么输出?
  • @FelippeDuarte 我添加了预期的输出

标签: php algorithm oop design-patterns


【解决方案1】:

您需要的是RecursiveIterator

你必须实现你自己的RecursiveIterator

class RecursiveContainerIterator extends IteratorIterator implements RecursiveIterator {
    public function getChildren() {
        if (is_array($this->current())) {
            return new RecursiveArrayIterator($this->current());
        } else if ($this->current() instanceof IteratorAggregate) {
            return $this->current()->getIterator();
        } else {
            throw new InvalidArgumentException('');
        }
    }

    public function hasChildren() {
        return is_array($this->current()) || $this->current() instanceof Traversable;
    }
}

class Container implements IteratorAggregate {
    private $children;
    public function __construct() {
        $this->children = $children = new ArrayObject();
    }

    public function addChild($child) {
        $this->children->append($child);
    }

    public function getChildren() {
        return $this->children;
    }

    public function getIterator() {
        return new RecursiveContainerIterator($this->children);
    }
}

$parent = new Container();
$child1 = new Container();
$child2 = new Container();
$grandChild1 = new Container();
$grandChild2 = new Container();
$grandChild3 = new Container();
$grandChild4 = new Container();

$parent->addChild($child1);
$parent->addChild($child2);
$parent->addChild(array(5, 6));

$child1->addChild($grandChild1);
$child1->addChild($grandChild2);

$child2->addChild($grandChild3);
$child2->addChild($grandChild4);

$grandChild1->addChild(1);
$grandChild2->addChild(2);
$grandChild3->addChild(3);
$grandChild3->addChild(4);

foreach (new RecursiveIteratorIterator($parent, RecursiveIteratorIterator::LEAVES_ONLY) as $child) {
    var_dump($child);
}

将输出:

int(1) 
int(2) 
int(3) 
int(4) 
int(5) 
int(6)

如果您需要处理对象本身而不仅仅是叶子,您可以使用RecursiveIteratorIterator::SELF_FIRST 标志。

【讨论】:

  • 在我的例子中,每个类都应该扩展容器,对吧?
【解决方案2】:

你的意思是这样的:

$objectArray[] = $A1;
$objectArray[] = $A2;
$objectArray[] = $B;
$objectArray[] = $A3;
$objectArray[] = $C;

foreach($objectArray as $obj){
   if(isset($obj->type)){
   //type is defined
  }else{

  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2020-04-24
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    相关资源
    最近更新 更多