在PHP中通过引用传递

时间:2012-12-06 16:07:01

标签: php

我对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;来修复它。通过查看,我明白这是因为引用按值(引用的副本)传递给函数。但这对我来说是一种意外/不一致的行为,所以问题是:他们选择这样做有什么特别的理由或好处吗?

2 个答案:

答案 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开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们包含标识符的副本,它指向同一个对象。

引自http://php.net/manual/en/language.oop5.references.php