我对PHP中的引用工作方式有一点普遍的不满,我自己来自Java背景。这可能是之前在SO上讨论的,所以如果这看起来多余,我很抱歉。
我将给出一个代码示例来说明问题。假设我们有一个Person类:
<?php
class Person
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
?>
以及以下用法:
<?php
require_once __DIR__ . '/Person.php';
function changeName(Person $person)
{
$person->setName("Michael");
}
function changePerson(Person $person)
{
$person = new Person("Jerry");
}
$person = new Person("John");
changeName($person);
echo $person->getName() . PHP_EOL;
changePerson($person);
echo $person->getName() . PHP_EOL;
?>
现在我和许多其他人从Java或C#编程到PHP,希望输出上面的代码:
Michael
Jerry
然而,它没有,它输出:
Michael
Michael
我知道可以通过使用&amp;来修复它。通过查看,我明白这是因为引用按值(引用的副本)传递给函数。但这对我来说是一种意外/不一致的行为,所以问题是:他们选择这样做有什么特别的理由或好处吗?
答案 0 :(得分:2)
对象本身实际上是通过引用传递的,否则您的第一个echo
将不会输出Michael
。
第二个示例中发生的情况是您销毁对原始对象的(本地)引用,并让您的变量名引用一个在该函数中具有局部作用域的新对象。
这对我来说是有道理的,因为你可以通过简单地为函数中的变量赋值一个新的值来摧毁/替换完全不同的对象。
答案 1 :(得分:1)
如果以这种方式使用,您的代码将按预期工作:
function changePerson(Person &$person) // <- & to state the reference
{
$person = new Person("Jerry");
}
$person = new Person("John");
changeName($person);
echo $person->getName() . PHP_EOL;
changePerson($person);
echo $person->getName() . PHP_EOL;
请参阅输出:http://codepad.org/eSt4Xcpr
经常提到的PHP 5 OOP的一个关键点是“默认情况下通过引用传递对象”。这不完全正确。
PHP引用是一个别名,它允许两个不同的变量写入相同的值。从PHP 5开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们包含标识符的副本,它指向同一个对象。