我遇到了一些有趣的事情: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 。如果我将needle更改为“ message1”或“ message3”,我会得到 false 。
这是如何工作的?该文档说它“检查数组中是否存在值”。 但是对对象的引用是“值”吗?有人可以澄清这个问题吗?
答案 0 :(得分:4)
从PHP docs:
从PHP 5开始,对象变量不再包含该对象本身作为值。它仅包含一个对象标识符,该标识符使对象访问者可以找到实际的对象。当对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们持有标识符的副本,该副本指向同一对象。
在“ OOP” PHP之前(即PHP <5),所有变量均通过 value 传递。您始终可以使用&
运算符通过引用传递变量,尽管这与使用指针的C之类的语言不同。在PHP5 +中,对象不是通过引用传递的,但是对象变量不包含对象本身,而是对象的标识符。当您将该变量传递给函数时,该标识符的副本将作为参数发送,就像其他任何原语一样。
要理解的最重要的事情是,当您将对象传递给函数时,对象本身不会传递,而是传递给对象的标识符。这些标识符提供对对象本身的访问权限,同时仍然允许您在实例之间进行数组搜索和相等性比较(===
)。
虽然PHP文档有点神秘,但我们可以看到对象标识符实际上是一个值:
不同的变量不是别名:它们持有标识符的副本,该副本指向同一对象。
包含对象的变量的值是对象标识符,而不是对象本身。
// $obj contains an identifier to an instance of `MyObject`
$obj = new MyObject();
当您将$obj
传递给函数时,该标识符的副本将作为参数发送。 PHP 始终按其值传递变量,除非明确指示使用&$var
通过引用传递。因此,要回答您的问题,对对象的引用(或更确切地说是 identifier )实际上是一个可用于比较对象特定实例的值。
修改
正如@Chris Anderson和@Lou所指出的,in_array
在默认情况下会进行松散比较。比较两个对象时,==
检查它们是相同的实例并具有相同的属性值,而===
检查它们是相同的类的实例。除非引起我的误解,否则您最初的问题是询问存储类实例的变量的行为方式,因此我的原始答案足以解决当前的问题。但是,重要的是要注意,如果没有明确要求严格比较(===
),则如果对象的值相同,您将得到true
。
答案 1 :(得分:2)
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 ] )
除非进行了严格设置,否则使用宽松的比较在干草堆中搜索针头。
松散比较(==):
使用比较运算符(==)时,以简单的方式比较对象变量,即:如果两个对象实例具有相同的属性和值(值与==进行比较),并且它们是的实例,则两个对象实例相等同一班。
严格比较(===):
使用身份运算符(===)时,对象变量是唯一且仅当它们引用相同类的相同实例时。