I'm using PHP 7.1.11
Consider below code :
<?php
class Test {
static public function getNew() {
return new static;
}
}
class Child extends Test {}
$obj1 = new Test();
$obj2 = new $obj1;
?>
Above code snippet has been taken from the PHP Manual.
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
?
What's the intention behind doing like this?
Is this kind of usage of new keyword recommended?
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;
(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)
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
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.
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
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).
The new
operator always creates a new instance of an object. It takes one argument, which can be a hard-coded class name:
$newObject = new MyClass();
Or a variable that contains a class name:
$className = 'MyClass';
$newObject = new $className();
Or an existing instance of an object of the type you want to create:
$oldObject = new MyClass();
$newObject = new $oldObject(); // Same as using "new MyClass();"
You'll probably never use the third case.