В прошлой статье посвященной объектно-ориентированному программированию в PHP мы рассмотрели основы ООП в PHP , а именно изучили понятия классов, объектов, свойств и методов, - и мы научились создавать простые классы и объекты в PHP .
В сегодняшней статье мы поговорим об конструкторах и деструкторах в ООП .
Конструкторы
Очень часто при создании экземпляра объекта на основе класса требуется выполнить какие-то базовые настройки, будь то установка свойств объекта или же открытие файлов конфигурации, да мало ли что еще. Именно для этих целей в ООП и существует метод конструктор. В версиях до PHP 5 имя метода конструктора совпадало с именем класса к которому он относится, а начиная с версии PHP 5 имя метода конструктора необходимо называть __construct() (это 2 подчеркивания перед словом construct()).
Конструктор автоматически вызывается при создании объекта. Давайте попробуем создать класс, который будет содержать метод __construct() :
Class MyClass { public function __construct() { echo "Я только что был создан!"; } } $myObject = new MyClass(); // выведет «Я только что был создан!»
MyClass содержит простой конструктор, который выводит сообщения с помощью оператора echo. В последней сточке кода мы создаем экземпляр класса MyClass() и когда это происходит PHP автоматически вызывает конструктор и на экран выводится сообщение «Я только что был создан!»
Давайте теперь посмотрим еще на один пример, в котором при создании объекта происходит инициализации его свойств:
Class Product{
private $title;
private $price;
private $discount;
public function __construct($title, $price, $discount) {
$this->title = $title;
$this->price = $price;
$this->discount = $discount;
}
public function getProduct(){
echo "Наименование товара: "".$this->title.""
";
echo "Цена товара: ".$this->price ." $
";
echo "Скидка: ".$this->discount ."%
";
}
}
$product = new Product("Мастер создания форм",20,25);
$product->getProduct();
Если запустить этот скрипт , то на экран будет выведена следующая информация:
Наименование товара: "Мастер создания форм" Цена товара: 20$ Скидка: 25%
Класс Product содержит 3 приватных (private) свойства: $title , $price и $discount , и конструктор, который принимает 3 аргумента: название товара, цена товара и скидка. Также имеется метод getProduct() , который выводит на экран информацию о товаре. В методе конструктора используется псевдопеременная $this для присвоения значений соответствующим свойствам объекта.
Далее мы создаем новый объект Product и передаем в нем информацию о товаре. Конструктор принимает эти данные и устанавливает соответствующие свойства объекта. И наконец вызывается метод getProduct(), который выводит на экран сохраненные значения свойств объекта.
Деструкторы
Подобно конструкторам в PHP существуют деструкторы, которые вызываются строго перед тем, как объект удаляется из памяти.
Это может понадобится, например, для удалению объектов, зависящих от удаляемого объекта, закрытие соединения с базой данных или файлов.
Примечание: PHP автоматически удаляет объект из памяти, когда не остается ни одной переменной, указывающей на него. Например, если вы создадите новый объект и сохраните его в переменной $myObject, а затем удалите ее с помощью метода unset($myObject) , то сам объект также удалится. Также, если вы создали локальную переменную в какой-либо функции, она (вместе с объектом) удалится, когда функция завершит работу.
В отличии от конструкторов, в деструкторы нельзя передавать никакие параметры!
Чтобы создать деструктор, добавьте в класс метод __destruct() . Вот простой пример:
Class MyClass { public function __destruct() { echo "Я деструктор. Объект был удален. Пока!"; } } $myObject = new MyClass(); unset($myObject); // отобразит "Я деструктор. Объект был удален. Пока!"
Мы создали простенький деструктор, который отображает на странице сообщение. Затем мы создали объект нашего класса и сразу же удалили его, вызвав метод unset() для переменной, которая ссылается на объект. Перед самым удалением объекта вызвался деструктор, который отобразил в браузере сообщение "Я деструктор. Объект был удален. Пока!" .
Также следует заметить, что деструктор вызывается и при выходе из скрипта, так как все объекты и переменные при выходе из метода удаляются. Давайте посмотрим на пример:
Class MyClass { public function __destruct() { echo "Я деструктор. Объект был удален. Пока!"; } } $myObject = new MyClass(); exit; // отобразит "Я деструктор. Объект был удален. Пока!"
Если работа скрипта прекратится из-за возникшей ошибки, деструктор тоже вызовется.
Примечание: при создании объектов класса-наследника, конструкторы класса-родителя не вызываются автоматически. Вызывается только конструктор самого наследника. Тем не менее вы можете вызвать конструктор родителя из класса-наследника таким образом: parent::__construct() . То же самое касается деструкторов. Вызвать деструктор родителя можно так: parent:__destruct() .
О на следовании мы поговорим в следующих статьях. А на сегодня все!
Столько воды утекло с тех пор как ПХП провозгласил себя ООП языком. Мне не удалось уточнить когда именно, но «On July 13, 2004, PHP 5 was released, powered by the new Zend Engine II. PHP 5 included new features such as improved support for object-oriented programming».
Т.е теоретически уже тогда появились конструкторы и деструкторы. Сам пользуюсь версией 5.3.2, но диву даюсь что он вытворяет.
Немного о себе. Я программист С++, опыт 4 года. Специализация - компьютерная графика и работа с сетью. А именно создание сетевых игр. Но таким играм нужен сервер, а серверу база игроков. А игроки хотят еще и сайт. «Зачем нанимать веб-программиста, я ведь и сам неплох. Заодно и язык изучу.»
Так я думал пол года назад, но до сих пор не могу понять!
^Примечание, явные исключения иногда работают верно. Буду ставить эксперементы что влияет.
Новая объектно-ориентированная модель в PHP5
Когда Зив Сераски (Zeev Suraski) добавил объектно-ориентированный (ОО) синтаксис в PHP 3, это можно было рассматривать как "синтаксический подсластитель для поддержки классов" ("syntactic sugar for accessing collections"). Объектно-ориентированная модель получила поддержку наследования и позволяла классу (и объекту) объединять методы и свойства, но не более того. Когда Зив и Анди переписали движок для PHP 4, это был полностью новый движок, работающий намного быстрее, намного стабильнее и с еще многими другими возможностями. Однако, изменения практически не затронули ОО модель, первоначально введенную еще в РНР 3.
Хотя объектная модель имела серьезные ограничения, она широко использовалась, часто в очень больших приложениях, написанных на PHP. Это победное шествование парадигмы ООП, даже такой ограниченной в РНР 4, привело к тому, что изменения объектной модели стали центральными в новом релизе РНР - PHP5.
Какие были ограничения в PHP 3 и 4? Самым большим ограничением (которое и приводило ко всем остальным ограничениям) был тот факт, что семантика экземпляра объекта была такой же, что и для родных типов. Как это фактически отражалось на разработчиках? Когда вы присваивали переменную (которая указывает на объект) другой переменной, то создавалась копия объекта. Мало того, что это влияло на производительность, но и это обычно приводило к ошибкам в приложении, потому что многие разработчики думали, что обе переменные будут указывать на тот же самый объект. А они указывали на разные копии того же самого объекта, поэтому, изменяя один объект, мы не меняли другой. Вот пример:
class
Person
{
var
$name
;
function
getName
() {
return
$this
->
name
;
}
function
setName
($name
) {
$this
->
name
=
$name
;
}
function
Person
($name
) {
$this
->
setName
($name
);
}
}
Function
changeName
($person
,
$name
) {
$person
->
setName
($name
);
}
$person
= new
Person
("Andi"
);
changeName
($person
,
"Stig"
);
print
$person
->
getName
();
?>
В РНР 4 этот код выведет "Andi". Причина кроется в том, что мы передаем объект $person в функцию changeName() по значению, а не по ссылке, таким образом, объект $person будет скопирован, и changeName() будет работать уже с копией объекта $person .
Такое поведение не является интуитивно понятным. Действительно, многие разработчики ожидали Java-подобного поведения. В Java, переменные фактически являются указателями на объект, и поэтому при дублировании будет скопирован указатель, а не сам объект.
Было два вида разработчиков: те, кто знал об этой проблеме, и те, кто не знал. Последние, обычно, не сталкивались с этой проблемой, потому что их код был написан так, что было безразлично, существует ли такая проблема или нет. Конечно, некоторые из этих разработчиков проводили бессонные ночи в "увлекательных" поисках "сверхъестественных" ошибок. Первая группа также имела проблему, поскольку приходилось вручную определять передачу объекта по ссылке, запрещая движку копировать объекты, и код был испещрен многочисленными знаками "& ".
Старая объектная модель приводит не только к вышеупомянутым проблемам, но также вскрывает более фундаментальные проблемы, которые на существующей объектной модели не позволяли осуществлять другие возможности.
В PHP 5 объектная модель была полностью переписана для того, чтобы сразу работать с указателями на объект. Если вы явно не клонируете объект, используя ключевое слово clone , вы никогда не будете работать с копией объекта, думая, что работаете с самим объектом. В PHP 5 уже не нужно явно передавать объекты или присваивать их по ссылке, это делается.
Обратите внимание: явная передача и присваивание по ссылке также поддерживается, на тот случай, если вы хотите изменить содержимое переменной или объекта.
Новый объектно-ориентированный подход в PHP5
Новые возможности объектной модели являются слишком многочисленными. Приведем обзор главных изменений:
Позволяют управлять доступом к методам и свойствам. Теперь видимость свойств и методов может быть определена ключевыми словами: public , private , protected . Модификатор public позволяет обращаться к свойствам и методам отовсюду. Модификатор private позволяет обращаться к свойствам и методам только внутри текущего класса. Модификатор protected позволяет обращаться к свойствам и методам только текущего класса и класса, который наследует свойства и методы текущего класса.
/**
* Define MyClass
*/
class
MyClass
{
public
$public
=
"Public"
;
protected
$protected
=
"Protected"
;
private
$private
=
"Private"
;
Function
printHello
()
{
echo
$this
->
public
;
echo
$this
->
protected
;
echo
$this
->
private
;
}
}
$obj
= new
MyClass
();
echo
$obj
->
public
;
// Works
echo
$obj
->
protected
;
// Fatal Error
echo
$obj
->
private
;
// Fatal Error
$obj
->
printHello
();
// Shows Public, Protected and Private
/**
* Define MyClass2
*/
class
MyClass2
extends
MyClass
{
// We can redeclare the public and protected method, but not private
protected
$protected
=
"Protected2"
;
Function
printHello
()
{
echo
$this
->
public
;
echo
$this
->
protected
;
echo
$this
->
private
;
}
}
$obj2
= new
MyClass2
();
echo
$obj
->
public
;
// Works
echo
$obj2
->
private
;
// Undefined
echo
$obj2
->
protected
;
// Fatal Error
$obj2
->
printHello
();
// Shows Public, Protected2, not Private
?>
PHP 5 позволяет объявлять методы-конструкторы. Классы, в которых объявлен метод-констуктор, будут вызывать этот метод при каждом создании нового объекта, так что это может оказаться полезным, чтобы, например, инициализировать какое-либо состояние объекта перед его использованием. Конструктор, ранее совпадавший с названием класса, теперь необходимо объявлять как __construct() , что позволит легче перемещать классы в иерархиях.Конструкторы в классах-родителях не вызываются автоматически. Чтобы вызвать конструктор, объявленный в родительском классе, следует обратиться к методу parent::__construct() .
class
BaseClass
{
function
__construct
() {
print
"Конструктор класса BaseClass\n"
;
}
}
Class
SubClass
extends
BaseClass
{
function
__construct
() {
parent
::
__construct
();
print
"Конструктор класса SubClass\n"
;
}
}
$obj
= new
BaseClass
();
$obj
= new
SubClass
();
?>
Если PHP 5 не может обнаружить объявленный метод __construct() , вызов конструктора произойдет по прежней схеме, через обращение к методу, имя которого соответствует имени класса. Может возникнуть только одна проблема совместимости старого кода, если в нём присутствуют классы с методами __construct() .
PHP 5 предоставляет концепцию деструкторов, сходную с теми, что применяются в других ОО языках, таких, как Java: когда освобождается последняя ссылка на объект, перед высвобождением памяти, занимаемой этим объектом, вызывается метод __destruct() , не принимающий параметров.
class
MyDestructableClass
{
function
__construct
() {
print
"Конструктор\n"
;
$this
->
name
=
"MyDestructableClass"
;
}
Function
__destruct
() {
print
"Уничтожается "
.
$this
->
name
.
"\n"
;
}
}
$obj
= new
MyDestructableClass
();
?>
Как и в случае с конструкторами, деструкторы, объявленные в родительском классе, не будут вызваны автоматически. Для вызова деструктора, объявленном в классе-родителе, следует обратиться к методу parent::__destruct() .
<<< Назад | Содержание | Вперед >>> |
Есть еще вопросы или что-то непонятно - добро пожаловать на наш | |
|
Деструктор класса PHP ООП — это специальная функция (принадлежащая к группе методов, известных как магические методы ), которая автоматически вызывается при удалении объекта. Деструктор не принимает никаких параметров. Понятие деструктора было введено в PHP5 , который реализует полноценную объектно-ориентированную модель. Дочерний класс может наследовать деструктор от родительского класса, если он не реализует деструктор сам.
При создании объекта может быть вызвана функция PHP-конструктора для инициализации переменных-членов. Деструктор выполняет обратную функцию, во время удаления объекта он освобождает память и ресурсы сервера. Деструктор также является важной функцией, так как ресурсы сервера ограничены, а десятки приложений различных отдельных сайтов работают на нем одновременно.
Следовательно, всегда полезно использовать PHP-деструктор . Например, в целях безопасности соединения с базой данных может потребоваться мгновенно закрыть ее сокет. В этом случае деструктор может оказаться весьма полезным.
Следует помнить, что в отличие от некоторых других языков программирования в ООП PHP существует уборщик мусора, который удаляет объекты, когда они больше не используются. Но если мы хотим удалить объект явно, PHP-деструктор подходит для этого.
Уборщик мусора PHP удаляет неиспользуемые объекты, но это может занять некоторое время, а до того момента за неиспользуемым объектом будут закреплены ресурсы. Используя деструктор, мы гарантируем, что ни один ресурс не задействуется впустую, он повышает эффективность приложений и сайтов. Если мы говорим об одном объекте, то использование деструктора не даст заметных изменений.
Но если приложение сложное, и в нем используется множество объектов, в этом случае использование PHP-деструктора может дать существенный эффект.
Согласно основам ООП PHP , при объявлении деструктора используется обозначение магических методов — два подчеркивания в начале и ключевое слово destruct :
Деструктор в PHP нельзя вызвать явно, так же, как мы не можем вызвать явно конструктор:
$myobject -> __destruct(); - невозможно
Еще один важный момент, касающийся деструктора: так же, как и конструктор, он вызывается для объекта только один раз — в момент удаления объекта.
Ниже приводится простой пример деструктора PHP :
public function __destruct() { print "{$this->Name} is destroyed...n"; }
Этот деструктор выводит сообщение о том, что объект удален. Мы можем закрыть соединение сокета с базой данных, однако я не пишу этот код. На самом деле весь процесс будет сложнее.
Надеюсь, вы разобрались в общем принципе работы деструктора:
public function __destruct() { Поместите в скобках ИСПОЛНЯЕМЫЙ КОД. }
Другой ООП PHP пример полного кода деструктора и конструктора:
name = "Car"; } function __destruct() { print "Destroying " . $this->name . "n"; } } $obj = new Car(); ?>
В PHP ООП деструктор вызывается только один раз. Лучше всего использовать Parent::_destruct() . Но родительский деструктор следует вызывать после того места, где размещается код деструктора, чтобы быть уверенным, что объект не будет удален, прежде чем он был использован в приложении.
Смотрите приведенный ниже пример:
public function __destruct() { print "{$this->Name} is destroyed...n"; parent:: _destruct(); }
Перевод статьи «PHP destructor » был подготовлен дружной командой проекта .
Хорошо Плохо
Конструктор класса вызывается автоматически всякий раз, когда создаются экземпляры класса и объекты из класса. В PHP ООП конструктор используется для инициализации свойств во время создания объекта. Конструктор выглядит как обычный метод PHP , разница заключается только в том, что он начинается с __ (двух символов подчеркивания ).
Конструктор класса PHP может содержать столько аргументов или параметров, сколько необходимо. Также можно определить конструктор вообще без параметров.
Важно отметить, что PHP-конструктор вызывается только один раз. И мы не можем вызвать конструктор явно, он вызывается автоматически при создании объекта.
Чтобы создать экземпляр класса, мы используем ключевое слово new, и в этот момент вызывается конструктор. В PHP родительский конструктор вызывается явно, если определен конструктор производного класса. Если требуется конструктор суперкласса, в производном классе нужен вызов parent::__construct() . Конструктор суперкласса может наследоваться, если производный класс не определяет конструктор сам. Наследуется конструктор так же, как и любой другой метод класса, если в суперклассе он не был объявлен как privat .
В PHP4 и ниже при определении конструктора использовался метод с таким же именем, что и класс (как в C++ и Java ). PHP5 ООП для определения конструктора любого класса содержит специальную функцию __construct() . Конструктор может содержать аргументы в соответствии с конкретными требованиями. Все объекты могут иметь встроенную функцию-конструктор, которая инициализирует при создании объекта его свойства. PHP позволяет создать только один конструктор для каждого класса, и мы не можем перегрузить конструктор.
Если существует несколько объявленных конструкторов, PHP будет вызывать первый и игнорировать остальные. Конструктор должен быть объявлен как public и может использоваться вне класса. Если конструктор объявлен как private , он может быть использован только с классом, в котором он определен. В случае если необходимо объявить его как private , нам нужно будет использовать вызов статической функции.
Так как конструктор является магическим методом, он будет иметь отличительную метку магических методов — два подчеркивания в начале. Для определения конструктора мы используем ключевое слово construct :
Construct(); // Конструктор без аргументов.
Давайте предположим, что у нас есть класс PHP Human , и он содержит переменную name . Исходный код будет выглядеть следующим образом:
Теперь мы добавим конструктор в этот класс. Помните, что в ООП PHP конструкторы — это магические методы, следовательно, они начинаются с двух символов подчеркивания и ключевого слова construct :
name= $nameofperson; } }
Создаем объекты этого класса с помощью ключевого слова new :
$firstObject = new Human("Joseph"); $secondObject= new Human("Taylor");
В этом ООП PHP примере мы создали объекты и инициализировали переменную $name . Первый объект будет хранить в переменной $name значение «Joseph «, а второй — «Taylor «. Мы присвоили объектам значения во время создания, чтобы избежать путаницы. Если бы для класса Human конструктор не был определен, то объекты создавались бы следующим образом:
$firstObject = new Human(); $secondObject = new Human();
Мы добавим новую переменную age в класс Human :
Сейчас наш класс содержит две переменные для хранения данных каждого объекта. Name и age представлены переменными $name и $age . Определяем конструктор еще раз, но на этот раз с двумя аргументами, один — чтобы установить экземпляр Name , а второй — age :
name= $nameofperson; $this -> age= $ageofperson; } } ?> $firstObject = new Human("Joseph", 23); $secondObject= new Human("Taylor", 35);
Мы создали два объекта, и они содержат начальные значения двух переменных-членов. Следует отметить, что согласно основам PHP ООП конструктор нельзя вызвать более одного раза, но мы можем изменять значения переменных-членов.
Поэтому в классе Human мы создадим два метода, один устанавливает возраст, а второй — имя. Конструктор используется, только чтобы задать начальные значения любой переменной. В дальнейшем, если нужно изменить это значение, мы будем использовать эти функции.
Тот же класс с двумя дополнительными методами:
name= $nameofperson; $this -> age= $ageofperson; } function set_name($newname){ $this ->name=$newname; } function set_age($newage){ $this ->age=$newage; } } ?>
Мы можем вызывать два новых метода, чтобы изменить имя или возраст. Добавим в пример еще два метода, чтобы вывести имя и возраст:
function get_name(){ return $this->name; } function get_age(){ return $this->age; }
Полный пример использования конструктора класса PHP ООП с четырьмя функциями:
name= $nameofperson; $this -> age= $ageofperson; } function set_name($newname){ $this ->name=$newname; } function set_age($newage){ $this ->age=$newage; } function get_name(){ return $this->name; } function get_age(){ return $this->age; } } ?>
Сначала мы определяем конструктор для класса bookinfo . Когда будут созданы объекты, мы передадим в конструктор значения для соответствующих экземпляров.
Давайте посмотрим, как используется конструктор. Сначала создаем простой класс с одним свойством и одной функцией:
name; } } ?>
Это простой класс, который содержит одну переменную данных, название машины, и метод вывода этого названия.
Теперь добавим конструктор, который будет задавать значение name в момент создания объекта. В ООП PHP код конструктора будет выглядеть следующим образом:
function __construct($param){ $this->name=$param; }
Добавив в наш класс конструктор, мы получим следующий код:
name=$param; } public function get_carname() { echo $this->name; } } ?>
Теперь создаем из класса объект:
$mycar= new car(“Honda”);
Выводим значение данных переменной через вызов метода get_carname() :
$mycar->get_carname();
Результат будет следующим:
Honda.
Это простой пример создания конструктора с инициализацией значения членов объекта. Это значение не фиксированное. Мы можем изменить его при необходимости. Тем не менее, это отличный способ инициализации объектов.
Используем конструктор в примере объекта PHP ООП , который мы рассматривали ранее. В классе bookinfo мы добавляем следующий код:
function __construct($param1, $ param2){ $this->price=$param1; $this->title=$param2; }
В примере после добавления этого кода инициализируются экземпляры класса, чтобы создать объекты. Тот же функционал достигается с помощью конструктора:
$astrology= new bookinfo(25, “Up to date Astrology”); $programming= new bookinfo(36, “Up to date PHP”); $database= new bookinfo(17, “Up to date DB”);
Теперь объекты созданы и инициализированы с названиями и ценами на момент создания объекта, это достигается с помощью конструктора.
Давайте получим доступ к методам get , чтобы вывести цены и названия книг. Используем те же методы, что и ранее:
$astrology->getBookTitle(); $programming-> getBookTitle(); $database-> getBookTitle(); $astrology->getBookPrice(); $programming-> getBookPrice (); $database-> getBookPrice ();
Этот PHP-код дает следующий результат:
Up to date astrology
Up to date PHP
Up to date DB
25
36
17