Почему и как новое ключевое слово используется с уже существующим объектом класса?

я использую 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;

1

Решение

$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 дал ….. он все еще вызывает конструктор, поэтому мы должны передать любые обязательные аргументы конструктора (или получить ошибку).

4

Другие решения

new Оператор всегда создает новый экземпляр объекта. Он принимает один аргумент, который может быть жестко заданным именем класса:

$newObject = new MyClass();

Или переменная, которая содержит имя класса:

$className = 'MyClass';
$newObject = new $className();

Или существующий экземпляр объекта того типа, который вы хотите создать:

$oldObject = new MyClass();
$newObject = new $oldObject(); // Same as using "new MyClass();"

Вы, вероятно, никогда не будете использовать третий случай.

2

По вопросам рекламы [email protected]