PHP 问题:对象属性增量

问题

以下代码段打印什么内容,为什么?

<?php

class MyClass {

    public $value;

}

 

function doSomething($object) {

    $object->value++;

}

 

$a = new MyClass();

$a->value = 1;

doSomething($a);

 

print $a->value;



 

回答

你可能认为上面代码的结果是1,但实际产生的值是2。这是因为虽然我们没有特意通过引用传递函数参数,但实际上是因为PHP中的所有对象都是通过引用传递的。

这是 PHP 的一个非常重要的特性,如果您在设计系统时不牢记它,几乎肯定会导致错误。可能会让您感到困惑的一件事是,即使在分配变量时,PHP 对象也是通过引用传递的。以下面的代码片段为例,它是上一个示例的后续内容。

$b = $a;

$b->value = 15;

echo $a->value;

您可能再次期望此代码的输出为 2(从上一个示例开始),但我们真正得到的是 15。发生这种情况是因为当您将一个对象分配给另一个变量时,您正在创建对原始对象的引用。因此,当我们尝试更改 $b 中“value”属性的值时,我们实际上是在更改原始对象中的值。

为了解决这个问题并创建一个单独的对象,我们使用clone关键字。clone 关键字将创建对象的浅表副本,该副本不会附加到原始对象。

$b = clone $a;

$b->value = 15;

echo $a->value;

上面的示例现在按预期打印出 2。

在克隆对象方面也有一些问题。请注意,我在介绍该术语时说的是“浅拷贝”。这是因为它会复制原始对象,但不会以相同的方式克隆所有内部对象。以下面的代码示例为例(它不遵循任何先前的示例)。

<?php

class MyClass {

    public $value;

}

 

class AnotherClass {

    public $something;

}

 

$a = new MyClass();

$a->value = new AnotherClass();

$a->value->something = 5;

 

echo $a->value->something . "\n";

 

$b = clone $a;

 

$b->value->something = 10;

 

echo $b->value->something . "\n";

echo $a->value->something . "\n";

如您所料,第一个 echo 调用打印出 5,但第二个调用都打印 10,因为虽然我们创建了原始对象的副本,但所有内部对象都是通过引用传递的。为了允许以相同的方式复制内部对象,可以使用调用的魔术方法__clone()。每当您克隆对象时都会调用此方法。重写上面的例子,我们可以创建一个新AnotherClass()对象,这样当我们更改对象 $a 中的值时,对象 $b 中的值也不会更改。

<?php

class MyClass {

    public $value;

 

    public function __clone() {

      $this->value = new AnotherClass();

    }

}

 

class AnotherClass {

  public $something;

}

 

$a = new MyClass();

$a->value = new AnotherClass();

$a->value->something = 5;

 

$b = clone $a;

 

$b->value->something = 10;

 

echo $b->value->something;

echo $a->value->something;

上面的例子现在打印 10 后跟 5。当 $b 中的相同值改变时,内部对象在 $a 中保存的值的原始值不会改变。

当然,在__clone()调用期间创建另一个对象意味着我们会丢失该对象的所有原始信息。我们可以手动转移这些值,但这是一种无法维护的方法。另一种__clone()方法是通过以下方式克隆方法内部的内部对象。

class MyClass {

    public $value;

 

    public function __clone() {

      $this->value = clone $this->value;

    }

}

这将创建从原始对象到当前对象的内部对象的副本。

以上是 PHP 问题:对象属性增量 的全部内容, 来源链接: utcz.com/z/354411.html

回到顶部