PHP中ArrayIterator、ArrayObject和Array的区别

PHP中ArrayIterator、ArrayObject和Array的区别,php,arrays,arrayobject,arrayiterator,Php,Arrays,Arrayobject,Arrayiterator,有人能解释一下PHP中ArrayIterator、ArrayObject和Array在功能和操作方面的根本区别吗?谢谢 PHP中的数组实际上是一个有序映射。地图是一种 将值与键关联。此类型针对几个方面进行了优化 不同用途;可以将其视为数组、列表(向量)、哈希 表(映射的实现)、字典、集合、堆栈、, 排队,可能更多。因为数组值可以是其他数组,所以树 多维数组也是可能的 此类允许对象作为数组使用 此迭代器允许在运行时取消设置和修改值和键 在数组和对象上迭代 当您想要在同一数组上迭代

有人能解释一下PHP中
ArrayIterator
ArrayObject
Array
在功能和操作方面的根本区别吗?谢谢

PHP中的数组实际上是一个有序映射。地图是一种 将值与键关联。此类型针对几个方面进行了优化 不同用途;可以将其视为数组、列表(向量)、哈希 表(映射的实现)、字典、集合、堆栈、, 排队,可能更多。因为数组值可以是其他数组,所以树 多维数组也是可能的

此类允许对象作为数组使用

此迭代器允许在运行时取消设置和修改值和键 在数组和对象上迭代

当您想要在同一数组上迭代多次时,需要 实例化ArrayObject并让它创建ArrayInterator实例 通过使用foreach或调用其 手动执行getIterator()方法


Array
是一种原生php类型。您可以使用php语言构造
array()

ArrayObject
是一个与数组完全相同的
对象。可以使用
new
关键字创建这些

ArrayIterator
类似于
ArrayObject
,但它可以在自身上迭代。也使用
new


比较
Array
vs(
ArrayObject
/
arrayInterator

它们都可以使用php的数组语法来使用,例如

$array[] = 'foo';
$object[] = 'foo';
// adds new element with the expected numeric key

$array['bar'] = 'foo';
$object['bar'] = 'foo';
// adds new element with the key "bar"

foreach($array as $value);
foreach($object as $value);
// iterating over the elements
但是,它们仍然是对象与数组,因此您会注意到

is_array($array); // true
is_array($object); // false

is_object($array); // false
is_object($object); // true
大多数php数组函数都需要数组,因此使用数组中的对象会引发错误。有许多这样的功能。例如

sort($array); // works as expected
sort($object); // Warning: sort() expects parameter 1 to be array, object given in ......
最后,对象可以执行您对
stdClass
对象的期望,即使用对象语法访问公共属性

$object->foo = 'bar'; // works
$array->foo = 'bar'; // Warning: Attempt to assign property of non-object in ....
数组(作为本机类型)比对象快得多。另一方面,
ArrayObject
&
ArrayIterator
类定义了某些方法,您可以使用这些方法,而数组则没有这样的方法


比较
ArrayObject
vs
ArrayIterator

这两个类之间的主要区别在于类具有的方法

ArrayIterator
实现了
Iterator
接口,该接口为它提供了与元素上的迭代/循环相关的方法
ArrayObject
有一个名为
exchangeArray
的方法,该方法将其内部数组与另一个数组交换。在
ArrayIterator
中实现类似的功能意味着要么创建一个新对象,要么通过键循环&
unset
将所有键逐个取消设置,然后从新数组中逐个设置元素

接下来,由于无法迭代
ArrayObject
,因此在
foreach
中使用它时,它会在内部创建一个
ArrayIterator
对象(与数组相同)。这意味着php创建了原始数据的一个副本&现在有两个具有相同内容的对象。对于大型阵列,这将被证明是低效的。但是,您可以指定迭代器使用哪个类,这样您就可以在代码中使用自定义迭代器



希望这是有帮助的。欢迎对此答案进行编辑。

ArrayObject和array有些相似。仅仅是对象(或本机类型)的集合。他们有一些不同的方法,你可以调用,但它主要归结为同一件事

然而,迭代器完全是另一回事。迭代器设计模式是保护数组的一种方法(使其仅可读)。让我们举下一个例子:

您有一个具有数组的类。您可以使用addSomethingToMyArray向该数组添加项。但是请注意,在将项实际添加到数组之前,我们会对其进行一些修改。这可以是任何东西,但让我们暂时表现得好像为我们要添加到数组中的每个项触发此方法是非常重要的

class A
{
    private $myArray;
    public function returnMyArray()
    {
        return $this->myArray;
    }

    public function addSomethingToMyArray( $item )
    {
        $this->doSomethingToItem( $item ); 
        array_push( $item );
    }
}
这里的问题是通过引用传递数组。这意味着实际使用returnMyArray的类将获得真正的myArray对象。这意味着除A以外的类可以向该数组添加内容,因此也可以在A内更改数组,而无需使用addSOmethingToMyArray。但我们需要做点什么,记得吗?这是一个类无法控制其自身内部状态的示例

解决这个问题的方法是使用迭代器。我们不传递数组,而是将数组传递给一个新对象,该对象只能从数组中读取内容。最简单的迭代器如下所示:

<?php

class MyIterator{

    private $array;
    private $index;

    public function __construct( $array )
    {
        $this->array = $array;
    }

    public function hasNext()
    {
        return count( $this->array ) > $this->index;
    }

    public function next()
    {
        $item = $this->array[ $this->index ];
        this->$index++;

        return $item;
    }       
}
while( $iterator->hasNext() )
    $item = $iterator->next();

现在,只有一种方法可以在A中向myArray添加项,即通过addSomethingToArray方法。这就是迭代器,它是数组的外壳,提供了一种叫做封装的东西

数组是PHP中的八种基本类型之一。尽管它有很多内置的实用功能,但它们都是过程性的

ArrayObject
ArrayIterator
都允许我们在面向对象程序(OOP)中使数组成为第一类公民

ArrayObject
ArrayIterator
之间的区别在于,由于
ArrayIterator
实现了
SeekableTerator
接口,所以您可以执行
$myArray->seek(10)数组迭代器的code>是一个对象,它使程序员能够遍历容器,尤其是列表。通常通过容器的接口提供各种类型的迭代器

ArrayObject
ArrayObject
之间没有太大区别,因为它们表示相同的东西,尽管使用
for( $arrayIterator->rewind(); $arrayIterator->valid(); $arrayIterator-
>next())
{    $key = $arrayIteartor->key();
     $value = $arrayIterator->current();
}
$data = [1,2,3,4,5];
//or
$data = array(1,2,3,4,5);
$array = new ArrayIterator();
var_dump(is_array($array)); // false
var_dump(is_object($array)); // true
$array[] = 'value one';
var_dump($array[0]);//string(9) "value one"

$array = new ArrayObject();
var_dump(is_array($array)); // false
var_dump(is_object($array)); // true
$array[] = 'value one';
var_dump($array[0]);//string(9) "value one"
//I originally made to this to solve some problem where generic conversion to XML via a foreach loop was used,
//and I had a special case where a particular API wanted each value to have the same name in the XML.
class SameKey extends ArrayIterator{

    public function key()
    {
        return "AlwaysTheSameKey";
    }
}

$extendedArrayIterator =  new SameKey(['value one','value two','value three']);
$extendedArrayIterator[] = 'another item added after construct';
//according to foreach there all the keys are the same
foreach ($extendedArrayIterator as $key => $value){
    echo "$key: ";//key is always the same
    var_dump($value);
}
//can still be access as array with index's if you need to differentiate the values
for ($i = 0; $i < count($extendedArrayIterator); $i++){
    echo "Index [$i]: ";
    var_dump($extendedArrayIterator[$i]);
}
//lets pretend I have many custom classes extending ArrayIterator each with a different behavior..
$O = new ArrayObject(['val1','val2','val3']);
//and I want to change the behavior on the fly dynamically by changing the iterator class
if ($some_condition = true) $O->setIteratorClass(SameKey::class);
foreach ($O as $key => $value){
    echo "$key: ";//AlwaysTheSameKey:
    var_dump($value);
}
class AustralianDates extends ArrayIterator{
    public function current()
    {
        return Date('d/m/Y',parent::current());
    }
}
$O = new ArrayObject([time(),time()+37474,time()+37845678]);
//and I want to change the behaviour on the fly dynamically by changing the iterator class
if ($some_condition = true) $O->setIteratorClass(AustralianDates::class);
foreach ($O as $key => $value){
    echo "$key: ";//AlwaysTheSameKey:
    var_dump($value);
}
//reference test
$I = new ArrayIterator(['mouse','tree','bike']);
foreach ($I as $key => &$value){
    $value = 'dog';
}
var_dump($I);//all values in the original are now 'dog'

$O = new ArrayObject(['mouse','tree','bike']);
foreach ($O as $key => &$value){
    $value = 'dog';
}
var_dump($O);//all values in the original are now 'dog'

$O->setIteratorClass(SameKey::class);
foreach ($O as $key => &$value){//PHP Fatal error:  An iterator cannot be used with foreach by reference
    $value = 'dog';
}
var_dump($O);