я использую 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.
Из приведенного выше кода я не могу понять, почему и как новое ключевое слово используется с существующим объектом class Test
?
Каково намерение сделать так?
Является ли этот вид использования новое ключевое слово рекомендуемые?
Если вы действительно хотите присвоить уже существующий объект класса какой-либо переменной, то этого нельзя сделать, просто написав инструкцию $obj2 = $obj1;
?
В чем разница между двумя ниже утверждениями? Какой из них лучше и должен быть предпочтительным?
$obj2 = new $obj1;
$obj2 = $obj1;
$obj2 = new $obj1;
(создает новый экземпляр объекта того же класса, что и $ obj1)! == $obj2 = $obj1;
(который создает $obj2
ссылка на $ obj1)! == $obj2 = clone $obj1;
(который создает новый $ obj2 со всеми значениями свойств, такими же, как у оригинала, но как новый экземпляр объекта)
Для 3 различных случаев, которые я привел в моих комментариях выше, давайте создадим простой класс и создадим его экземпляр:
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
Теперь, если мы просто назначим новую переменную оригиналу, мы установим указатель на оригинал (потому что это объект), аналогично ссылке
// 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
Любые изменения одного из них будут отражены в другом, потому что они указывают на один и тот же экземпляр объекта.
Если мы используем clone
затем мы создаем совершенно новый экземпляр объекта, но уже заполнив его значениями свойств из исходного
// 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
Теперь, если мы изменим свойства оригинала, это не повлияет на клон (или наоборот), потому что они являются уникальными экземплярами.
У нас есть третий случай, где мы используем new
с экземпляром, а не именем класса.
// 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
дал ….. он все еще вызывает конструктор, поэтому мы должны передать любые обязательные аргументы конструктора (или получить ошибку).
new
Оператор всегда создает новый экземпляр объекта. Он принимает один аргумент, который может быть жестко заданным именем класса:
$newObject = new MyClass();
Или переменная, которая содержит имя класса:
$className = 'MyClass';
$newObject = new $className();
Или существующий экземпляр объекта того типа, который вы хотите создать:
$oldObject = new MyClass();
$newObject = new $oldObject(); // Same as using "new MyClass();"
Вы, вероятно, никогда не будете использовать третий случай.