为什么以及如何将new关键字与类的现有对象一起使用?
我正在使用 PHP 7.1.11
考虑以下代码:
<?php
class Test {
static public function getNew() {
return new static;
}
}
class Child extends Test {}
$obj1 = new Test();
$obj2 = new $obj1;
?>
以上代码段摘自 PHP手册.
从上面的代码中,我无法理解为什么 new关键字以及为什么与class Test
的现有对象一起使用?
From the above code I'm not able to understand why and how the new keyword is being used with the existing object of a class Test
?
这样做的目的是什么?
是否建议使用这种 new关键字?
如果您真的想将某个类的现有对象分配给某个变量,那么仅通过编写语句$obj2 = $obj1;
即可完成吗?
If you really want to assign an already existing object of a class to some variable then can't it be done by simply writing the statement $obj2 = $obj1;
?
以下两个语句有什么区别?哪个更好,应该首选?
What's the difference between below two statements? Which one is better and should be preferred?
$obj2 = new $obj1;
$obj2 = $obj1;
$obj2 = new $obj1;
(创建与$ obj1相同类的对象的新实例)!== $obj2 = $obj1;
(创建$obj2
引用到$ obj1)!== $obj2 = clone $obj1;
(它将创建一个新的$ obj2,其属性值与原始属性值相同,但作为一个新的对象实例)
$obj2 = new $obj1;
(creates a new instance of an object of the same class as $obj1) !== $obj2 = $obj1;
(which creates $obj2
a reference to $obj1) !== $obj2 = clone $obj1;
(which creates a new $obj2 with all the same property values as the original but as a new object instance)
对于我在上面的评论中引用的3种不同情况,让我们创建一个简单的类并将其实例化:
For the 3 different cases that I cited in my comments above, let's create a simple class and instantiate it:
class User {
public $firstname;
public $lastname;
public function __construct($firstname = 'TEST', $lastname = 'USER') {
$this->firstname = $firstname;
$this->lastname = $lastname;
}
public function getName() {
return implode(' ', [$this->firstname, $this->lastname]);
}
}
// original instance of a User
$obj1 = new User('Mark', 'Baker');
var_dump($obj1->getName()); // Mark Baker
现在,如果我们简单地为原始变量分配一个新变量,我们将设置一个指向原始变量的指针(因为它是一个对象),类似于引用
Now if we simply assign a new variable to the original, we're setting a pointer to the original (because it's an object), similar to a reference
// Simply set reference to our original User
$obj2 = $obj1;
var_dump($obj2->getName()); // Mark Baker
// And if we change properties of the instance, it changes for both because it's a reference
$obj2->firstname = 'David Mark';
var_dump($obj2->getName()); // David Mark Baker
var_dump($obj1->getName()); // David Mark Baker
对任何一个的任何更改都会反映在另一个中,因为它们都指向相同的对象实例
Any changes to either will be reflected in the other, because they are pointing to the same object instance
如果使用clone
,则说明我们正在创建一个全新的对象实例,但是已经填充了原始对象的属性值
If we use clone
, then we're creating a brand new object instance, but already populated with the property values from the original
// Clone the original object, this will create a new instance but will inherit property values of the original
$obj3 = clone $obj1;
var_dump($obj3->getName()); // David Mark Baker
// But changing properties of the clone won't affect the original in any way
$obj3->firstname = 'Mark';
var_dump($obj3->getName()); // Mark Baker
var_dump($obj1->getName()); // David Mark Baker
现在,如果我们更改原始属性,它将不会影响克隆(反之亦然),因为它们是唯一的实例.
Now if we change properties of the original, it won't affect the clone (or vice versa) because they are unique instances.
我们有第三种情况,我们将new
与实例而不是类名一起使用.
The we have the third case, where we're using new
with an instance rather than class name.
// Now create a new instance of the same type of object as your original User
// If we had mandatory constructor arguments, then we'd have to provide them $obj4 = new $obj1('a', 'b');
// But because they're optional, we can get away with allowing the defaults
$obj4 = new $obj1;
var_dump($obj4->getName()); // TEST USER
如果我们不知道$obj1
是什么类类型,那么没关系(尽管很容易找出来).这样就创建了一个新的实例,无论它是什么类$obj1
,都没有clone
给出的属性继承,也没有像$obj2 = $obj1
那样给出的引用..它仍然调用构造函数,因此我们必须传递任何强制的构造函数参数(或得到错误).
If we didn't know what class type $obj1
was, then it doesn't matter (though it would have been easy enough to find out). This creates a brand new instance of whatever class $obj1
was, without the property inheritance that clone
gives, nor is it reference like $obj2 = $obj1
gave..... it still calls the constructor, so we have to pass any mandatory constructor arguments (or get an error).