Как скопировать объект в PHP? - PullRequest
0 голосов
/ 07 января 2010

У меня есть простой класс «размеры», содержащий свойство width / height и конструктор для их установки.

У меня есть функция (для изменения размеров), которая принимает два объекта измерений - один для изменения размера, а другой содержит максимальный размер. Следует уменьшить размеры первого параметра, чтобы они «вписывались» во второй параметр.

Затем возвращается первый, только что измененный размер.

Вызывающий объект передает объект измерений и возвращает возвращаемое значение в другое - потому что он должен сохранить исходный объект. Но тот, который передается в функцию, модифицируется.

Это было удивительно, так как я не взял это по ссылке:

private function scale_image_dimensions(Dimensions $dimensions, Dimensions $max_size) {

    if( $dimensions->width > $max_size->width ) {
        $dimensions->height = $dimensions->height / ($dimensions->width / $max_size->width);
        $dimensions->width = $max_size->width;
    }

    if( $dimensions->height > $max_size->height ) {
        $dimensions->width = $dimensions->width / ($dimensions->height / $max_size->height);
        $dimensions->height = $max_size->height;
    }

    return $dimensions;
}

Как указать, что я хочу, чтобы функция делала копию переданных в нее объектов, а затем возвращала один из них?

обновление

Кажется, что-то еще подозрительно - я изменил аргумент с $dimensions на $adimensions и поставил $dimensions = $adimensions в начале функции.

Но переменная вызывающего все еще изменяется! Работает ли задание также по ссылке? Я имею в виду ... Нет способа перегрузить оператор присваивания или конструктор копирования, так что ... что мне делать? Если мне нужна копия, я должен явно инициализировать одну каждый раз ?

Ответы [ 5 ]

3 голосов
/ 07 января 2010

Думаю, многие люди полностью против клонирования , я за это .

Редактировать: Объект присваивается по ссылке и также передается по ссылке.

Если вам нужен глубокий клон объекта, используйте ключевое слово clone, как в $cloned = clone $dimensions, а также определите магический метод __clone() в вашем классе Dimensions, чтобы убедиться, что любые ссылки на объекты внутри Dimensions действительно клонирован также.

2 голосов
/ 07 января 2010

Все объекты по умолчанию называются ссылками. Чтобы сделать копию объекта, необходимо клонировать его с помощью ключевого слова clone.

private function scale_image_dimensions(Dimensions $dimensions, Dimensions $max_size) {
    $old_dimensions = $dimensions;
    $dimensions = clone $dimensions;

    if( $dimensions->width > $max_size->width ) {
        $dimensions->height = $dimensions->height / ($dimensions->width / $max_size->width);
        $dimensions->width = $max_size->width;
    }

    if( $dimensions->height > $max_size->height ) {
        $dimensions->width = $dimensions->width / ($dimensions->height / $max_size->height);
        $dimensions->height = $max_size->height;
    }

    return $dimensions;
}

Это удерживает PHP от создания большого количества объектов, и обычно люди хотят, чтобы объекты передавались по ссылке в любом случае.

Классы PHP не очень часто используются в качестве утилиты «Хранение данных», поскольку массивы часто работают так же хорошо.

Но если вы переходите на другой язык, который использует много классов для хранения данных, я вижу, что это будет большой проблемой.

1 голос
/ 07 января 2010

Параметры, в некотором смысле, передаются по значению, поскольку вы можете переназначить размеры $ без влияния на оригинал.

Но переменные объекта - это просто указатели на фактический объект, поэтому вы правы, что изменение их переменных-членов повлияет на исходный объект.

Если вы хотите избежать этого, вам нужно клонировать объекты. PHP имеет функцию клонирование , но имейте в виду, что по умолчанию он делает полные копии. Поэтому, если ваши объекты содержат другие объекты, вы не получите их клонов; просто ссылки на оригиналы. Вы можете просто захотеть вручную создавать новые объекты и копировать их значения.

1 голос
/ 07 января 2010

PHP5 автоматически обрабатывает параметры как ссылки. Вы можете клонировать объект, используя ключевое слово clone.

$newObject = clone $originalObject;

Одна вещь, о которой вы должны беспокоиться, это разница между полной и мелкой копиями при клонировании. По умолчанию клон будет делать только поверхностную копию.

1 голос
/ 07 января 2010

Может ключевое слово клона будет то, что вы ищете?

$return_dimensions = clone $dimensions;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...