PHP-кейс #1: “Переменные, Классы и Клонирование”
В одном из предыдущих постов, я уже писал, что мне иногда приходят на почту и в аську вопросы от читателей по поводу тех или иных вопросов разработки. Иногда простые, иногда посложнее. Но так или иначе, у меня уже “подсобралось” коллекция вопросиков и ситуаций “на догадку”. Назову их по аналогии из бизнеса “PHP - кейсами”. Периодически я буду публиковать наиболее показательные из них. Я не буду брать дословные вопросы из своей переписки с читателями. Скорее всего это будут некие абстрактные примеры в стиле “foo-bar” и “MyCar-YouCar”.
Если вы часто в практике встречаетесь с подобными “PHP-кейсами” - присылайте или оставляйте в комментариях!
Итак, начнем с простого, но очень полезного для новичков PHP ООП.
PHP-Кейс #1. Классы и переменные
Рассмотрим простейший код:
/** * @project PHP-Case #1. * @author Alex Kachayev * http://www.kachayev.ru */ $car_1 = 'Merce'; $car_2 = $car_1; $car_1 = 'Boing'; print $car_2;
Даже в детском саду вам скажут, что на экран будет выведено
Merce
Изменение в первой переменной, никак не отобразилось на второй.
Рассмотрим теперь другую ситуацию.
/** * @project PHP-Case #1. * @author Alex Kachayev * http://www.kachayev.ru */ class Car { public $model; public function __construct( $model ) { $this->model = $model; } } $myOwnCar = new Car('BMW'); print 'My car: '. $myOwnCar->model ."\n"; /** * Даю тебе машину, такую же как моя :) */ $youCar = $myOwnCar; /** * У нас с тобой одинаковые модели */ print 'You car: '. $youCar->model ."\n"; /** * Мне надоело BMW, собираю все деньги, покупаю Астон Мартин */ $myOwnCar->model = 'Aston Martin'; print 'My new car: '. $myOwnCar->model ."\n"; /** * Посмотрим, какая машина у тебя? */ print 'You new car: '. $youCar->model ."\n";
Итак, что мы получим на выходе? Вот ответ:
My car: BMW
You car: BMW
My new car: Aston Martin
You new car: Aston Martin
Почему мы получили именно такой результат… Думаем и читаем мануалы :).
Давайте пойдем еще дальше, и дополнил наш кейс новым кодом: предположим мой машина разбилась…
/** * Разбиваем мою машину :) */ $myOwnCar = null; /** * Посмотрим теперь на наши машины */ var_dump($myOwnCar); var_dump($youCar);
Что получим на выходе? Вот такое вот “жизненное безобразие”:
My car: BMW
You car: BMW
My new car: Aston Martin
You new car: Aston Martin
NULL
object(Car)#1 (1) {
["model"]=>
string(12) “Aston Martin”
}
Т.е. твоя машина - как новенькая, а от моей только дырка от руля осталась :).
Клонирование
А если на практике мне понадобиться сделать “независимую копию объекта класса”? Для этого можно можно (и нужно) использовать clone.
Добавляем в код следующие строки:
/** * "Клонируем" твою машину для "кого-то" */ $somebodyCar = clone $youCar; /** * Теперь "кто-то" ездит на таком же Aston Martin`e */ print 'Somebody`s Car: '. $somebodyCar->model ."\n"; /** * А ты меняешь модель на Audi */ $youCar->model = 'Audi'; /** * Кто теперь на чем ездит? */ print 'Your New Car: '. $youCar->model ."\n"; print 'Somebody`s new Car: '. $somebodyCar->model ."\n";
Результатом выполнения данного кода будет следующее:
Somebody`s Car: Aston Martin
Your New Car: Audi
Somebody`s New Car: Aston Martin
Поведение класса при использовании конструкции clone, кстати, можно предопределить в самом классе, использую магический __clone() (читать вот здесь).
Если Вы - жадный программист, и не хотите, чтобы кто-то “клонировал” вашу машину, можете изменить код класса Car следующим образом:
class Car { /** * @var string Здесь мы будем хранить название модели */ public $model; /** * @const string Сообщение, выдаваемое при попытке клонировать объект */ const CLONE_ERROR_MESSAGE = 'Клонирование запрещено'; public function __construct( $model ) { $this->model = $model; } /** * Объявлении функции как private запрещает ее вызов вне класса * поэтому извне объект клонировать никто не сможет. * При попытке же клонировать объект изнутри класса * будет сгенерировано E_USER_ERROR */ private function __clone() { trigger_error(self::CLONE_ERROR_MESSAGE, E_USER_ERROR); } }
А если же вы не просто жадный программист, а еще и программист с чувством юмора, то вы напишите так:
class Car { /** * @var string Здесь мы будем хранить название модели */ public $model; /** * @const string Сообщение, выдаваемое при попытке клонировать объект */ const CLONE_ERROR_MESSAGE = 'Клонирование запрещено'; public function __construct( $model ) { $this->model = $model; } /** * Теперь любой, кто клонирует объект, * будет кататься на Ланосе :) */ public function __clone() { $this->model = 'Lanos'; } }
Выполним предыдущий код с этим классом и получим на выходе:
Somebody`s Car: Lanos
Your New Car: Audi
Somebody`s New Car: Lanos
Учим матчасть!
С этого времени буду публиковать у себя в блоге подобные кейсы для разминки мозгов и тренировки внимательности.
Понравился пост? Будь в курсе последних событий: подпишись на RSS-ленту.!
Также читайте по теме:
- 18 февраля

Хорошо бы указать, что примеры приводятся для PHP5. Это, конечно, понятно из кода классов, но новичек (а ведь на них расчитан этот пост?) может пропустить этот момент.
Да нормально написано, все очень хорошо растолковывается, по крайней мере мне как новичку все понятно. Спасибо
2Oleg:
Знаете, Олег, скорее надо было бы сделать наоборот - сказать что в PHP4 не работает. Уже пора делать PHP5 стандартом de facto, а уже как второстепенное вспоминать - мол, раньше, в PHP4 было по другому
Да, с этими ссылками беда просто какая то. Был заказ на кмс, основанную на массивах, так там чтобы ссылаться на какой то элемент надо было
писать
7\4\5\3\
и тд. Потом разбивать на \ и еще вначале планировалось возвращять ссылку & на элемент, дык для удаления - удаляется Связь! а не элеменент. Жаль что разработчики ядра это не продумал
[...] Постовой: Белый Нигер толкает качевый музон в массы Neon чуть не сломал свое счастье Качаев проводит мини ликбез по ООП в пхп [...]
Ваша машина - это “YourCar”, а не “YouCar”.
Хорошая практика ООП заключается в том, чтобы инкапсулировать связанные данные, поэтому переменные класса стоит объявлять приватными и разрешать (или не разрешать) безопасный доступ к ним через get- и set-методы, так что учите матчасть вы.
Вы прививаете новичкам плохой стиль программирования, а работа ссылок в PHP и использование __clone() - это детский сад, вторая группа.
Программист с чувством юмора - это пиздец.
2Александр:
“…ООП заключается в том, чтобы инкапсулировать связанные данные, поэтому переменные класса стоит объявлять приватными и разрешать (или не разрешать) безопасный доступ к ним через get- и set-методы…”
Заметка не об этом, если вы не заметили. Классы написаны для демонстрации, а не для использования в конкретном проекте.
“…а работа ссылок в PHP и использование __clone() - это детский сад, вторая группа…”
Ну, естественно, вы об этом знали с самого рождения! А кому-то не повезло, и он родился не зная об этом. Значит у него один путь - когда-то об этом узнать. Например, читая подобные записи в блогах.
Прикольненько, мне понравился пример с машинкой
Хотя между php и C++ говорят, много общего, все равно мне больше нравится на втором работать. А в целом неплохой вводной мануальчик