为什么 PHP 的 in_array() 方法可以识别数组中对象的特定实例的存在?



我发现了一些有趣的东西:in_array((函数不仅在"needle"是特定值时有效,而且在它是特定对象实例时也有效。我举一个例子:

class Message{
private $str;
function __construct($str){
$this->str= $str;
}
}
$message1 = new Message('Hey there!');
$message2 = new Message('sup');
$message3 = new Message('yo');
$arr= [$message2, 545,'hey'];
echo in_array($message2 ,$arr) ? 'true' : 'false';

正如您所看到的,我正在创建某个类的不同实例。对其中一个实例的引用被放置到数组中。

当我检查数组中是否存在"message2"对象时,我得到true。如果我将针更改为"message1"或"message3",我将得到false

这是怎么回事?文档中说它"检查数组中是否存在值">但是对对象的引用是"值"吗有人能澄清这个问题吗?

来自PHP文档:

从PHP 5开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,该标识符允许对象访问器查找实际对象。当一个对象通过参数发送、返回或分配给另一个变量时,不同的变量不是别名:它们持有指向同一对象的标识符的副本。

在"OOP"PHP(即PHP<5(出现之前,所有变量都通过传递。您总是可以使用&运算符通过引用传递变量,尽管这与使用指针的C语言不同。在PHP5+中,对象不是通过引用传递的,但对象变量不包含对象本身,而是对象的标识符。当您将该变量传递给函数时,该标识符的副本将作为参数发送,就像任何其他基元一样。

要理解的最重要的一点是,当您将对象传递给函数时,对象本身并不是传递的,而是传递给对象的标识符。这些标识符提供了对对象本身的访问,同时仍然允许您在实例之间执行数组搜索和相等性比较(===(。

虽然PHP文档有点神秘,但我们可以看到对象标识符实际上是一个值:

不同的变量不是别名:它们持有指向同一对象的标识符的副本。

包含对象的变量的值是对象标识符,而不是对象本身。

// $obj contains an identifier to an instance of `MyObject`
$obj = new MyObject();

$obj传递给函数时,该标识符的副本将作为参数发送。除非明确指示使用&$var通过引用传递,否则PHP始终按变量的值传递变量。因此,为了回答您的问题,对对象的引用(或者更确切地说,标识符(实际上是一个可以用于比较对象的特定实例的值。


编辑

正如@Chris Anderson和@Lou所指出的,in_array默认情况下会进行松散比较。当比较两个对象时,==会检查它们是否为同一实例并具有相同的属性值,而===会检查它们是同一类的实例。除非我误解了,否则你最初的问题是问存储类实例的变量的行为性质,所以我最初的答案应该足以回答手头的问题。但是,重要的是要注意,在不明确要求严格比较(===(的情况下,如果对象的值相同,则会得到true

Ref:比较对象

class Message{
private $str;
function __construct($str){
$this->str= $str;
}
}
$message1 = new Message('Hey there!');
$message2 = new Message('yo');
$message3 = new Message('yo');
$arr = [$message2, 545,'hey'];
//loose comparison using == 
echo in_array($message3 ,$arr) ? 'true' : 'false'; // returns true
//strict comparison using ===
echo in_array($message3 ,$arr, true) ? 'true' : 'false'; // returns false

in_array((

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

除非设置了strict,否则使用松散比较在haystack中搜索针。

松散比较(==(:

使用比较运算符(==(时,对象变量以一种简单的方式进行比较,即:如果两个对象实例具有相同的属性和值(值与==进行比较(,则它们是相等的,并且是同一类的实例。

严格比较(==(:

使用标识运算符(==(时,对象变量是相同的,当且仅当它们引用同一类的同一实例时。

最新更新