Операции с объектами
Перечисление свойств объектов
При работе с объектами может возникнуть необходимость в последовательном перечислении свойств текущего объекта. В этом случае может пригодиться известный нам цикл foreach, который позволяет получить доступ ко всем открытым для него свойствам и их значениям (см. пример 6.17).
<?php class iter_class{ public $var_1='value_1'; //Общедоступное public $var_2='value_2'; //Общедоступное protected $protected_var='protected_var'; //Защищенное private $private_var='private_var'; //Закрытое function iterate_properties(){ //Метод для перечисления свойств echo "Свойства класса iter_class, перечисляемые циклом изнутри класса:<br>"; foreach($this as $key=>$value){ //Перечисляем внутри класса echo "{$key}=>{$value}".'<br>'; } } } $class = new iter_class(); $class->iterate_properties(); echo "<br> Свойства класса iter_class, перечисляемые циклом снаружи класса:<br>"; foreach($class as $key=>$value){ //Перечисляем снаружи класса echo "{$key}=>{$value}".'<br>'; } ?>
Пример 6.17. Перечисление свойств объектов циклом foreach
Как видим, цикл foreach перечисляет все доступные для него в данной области видимости свойства объекта так, как-будто он имеет дело с обычным массивом.
Возможности PHP по итерации объектов не исчерпываются только лишь циклом foreach, поскольку для этих целей имеются также и специальные интерфейсы, позволяющие реализовывать итерацию объектов практически любым удобным для программиста способом. Однако здесь мы их рассматривать не будем, а вернемся к этому вопросу во второй части учебника.
Сравнение объектов
Также как и другие типы данных, объекты можно сравнивать между собой. При использовании оператора нестрогого сравнения '==' два объекта будут считаться равными, если они являются экземплярами одного и того же класса и имеют один и тот же набор свойств и соответствующих им значений. А в случае использования оператора идентичности '===', объекты будут считаться тождественно равными (идентичными) только тогда, когда они ссылаются на один и тот же экземпляр одного и того же класса (см. пример 6.18).
<?php class my_class_1{ public $var_1='value_1'; //Общедоступное protected $protected_var='protected_var'; //Защищенное public function func(){ //Метод класса echo 'Функция func'; } } class my_class_2{ public $var_1='value_1'; //Общедоступное protected $protected_var='protected_var'; //Защищенное public function func(){ //Метод класса echo 'Функция func'; } } $obj_1=new my_class_1(); //Создаем объекты одного $obj_2=new my_class_1(); //и того же класса echo $obj_1==$obj_2; //Выведет '1' (т.е. true), т.к. объекты принадлежат //одному классу, имеют одинаковые свойства и их значения echo $obj_1===$obj_2; //Выведет '' (т.е. false), т.к. объекты принадлежат //одному классу, но являются разными экземплярами $obj_2->var_1='new value'; //Изменим значение свойства второго объекта echo $obj_1==$obj_2; //Выведет '' (т.е. false), т.к. объекты принадлежат //одному классу, имеют одинаковые свойства, но //значения одного из них ($var_1) различаются $obj_3=$obj_1; echo $obj_3===$obj_1; //Выведет '1' (т.е. true), т.к. переменные содержат //ссылки на один и тот же экземпляр (new my_class_1) $obj_4=new my_class_2(); //Создаем объект другого класса echo $obj_4==$obj_1; //Выведет '' (т.е. false), т.к. объекты принадлежат //разным классам ?>
Пример 6.18. Сравнение объектов
Отметим, что расширения могут определять собственные правила для сравнения своих объектов.
Клонирование объекта, оператор clone
Как говорилось выше, когда мы присваиваем одну переменную, содержащую идентификатор какого-нибудь объекта, другой переменной, мы получаем две переменные, содержащие один и тот же идентификатор, указывающий на один и тот же объект. Если же нам необходимо создать именно копию объекта, а не копию его идентификатора, то необходимо воспользоваться оператором clone, который создаст объект с полностью идентичными свойствами, которые можно изменить по своему усмотрению при помощи метода __clone, вызывающегося только при каждом новом клонировании объекта (см. пример 6.19).
<?php class cloneable_class{ public $var_1=0; //Создаем свойство public function __construct(){ //Каждый раз при создании нового объекта ++$this->var_1; //$var_1 будет увеличиваться на 1 } public function __clone(){ //Метод запускается только при клонировании ++$this->var_1; //объекта и увеличивает $var_1 на 1 } } $obj_1 = new cloneable_class(); //Создаем объект класса cloneable_class //Теперь просто копируем идентификатор, который указывает на new cloneable_class(), //при этом метод __clone не запускается $obj_2=$obj_1; echo $obj_1->var_1.'<br>'; //Выведет '1' echo $obj_2->var_1.'<br>'; //Выведет '1' $obj_1->var_1=5; //Изменили значение свойства на 5 echo $obj_2->var_1.'<br>'; //Выведет '5', т.к. обе переменные ссылаются //на один и тот же объект //Клонируем $obj_1, при этом создается реальный объект-клон с запуском метода__clone $obj_3=clone $obj_1; echo $obj_1->var_1.'<br>'; //Выведет '5' echo $obj_3->var_1.'<br>'; //Выведет '6' $obj_1->var_1=10; //Изменили значение исходного объекта на 10 echo $obj_3->var_1; //Выведет по-прежнему '6', т.к. переменные $obj_3 //и $obj_1 ссылаются на разные объекты ?>
Пример 6.19. Клонирование объектов
Таким образом, если мы собираемся клонировать объект и хотим при клонировании изменить некоторые его свойства, то необходимо заранее в исходном классе объявить метод __clone, который будет вызываться по завершении каждого нового процесса клонирования объекта. При этом нужно помнить, что вызов данного метода не может быть выполнен непосредственно. В случае отсутствия метода __clone в исходном объекте в результате клонирования будет создана простая неизмененная копия объекта. В любом случае после создания клон станет доступным для независимого использования.