Основы
Каждое определение класса начинается с ключевого слова class, затем следует имя класса, и далее пара фигурных скобок, которые заключают в себе определение свойств и методов этого класса.
Именем класса может быть любое слово, при условии, что оно не входит в список зарезервированных слов PHP, начинается с буквы или символа подчеркивания и за которым следует любое количество букв, цифр или символов подчеркивания. Если задать эти правила в виде регулярного выражения, то получится следующее выражение: ^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$.
Класс может содержать собственные константы, переменные (называемые свойствами) и функции (называемые методами).
Пример #1 Простое определение класса
class SimpleClass
// объявление свойства
public $var = ‘значение по умолчанию’ ;
?php
// объявление метода
public function displayVar () echo $this -> var ;
>
>
?>
Псевдо-переменная $this доступна в том случае, если метод был вызван в контексте объекта. $this является ссылкой на вызываемый объект. Обычно это тот объект, которому принадлежит вызванный метод, но может быть и другой объект, если метод был вызван статически из контекста другого объекта. Это показано на следующих примерах:
Пример #2 Переменная $this
class A
function foo ()
if (isset( $this )) echo ‘$this определена (‘ ;
echo get_class ( $this );
echo «)\n» ;
> else echo «\$this не определена.\n» ;
>
>
>
?php
class B
function bar ()
// Замечание: следующая строка вызовет предупреждение, если включен параметр E_STRICT.
A :: foo ();
>
>
// Замечание: следующая строка вызовет предупреждение, если включен параметр E_STRICT.
A :: foo ();
$b = new B ();
$b -> bar ();
// Замечание: следующая строка вызовет предупреждение, если включен параметр E_STRICT.
B :: bar ();
?>
Результат выполнения данного примера:
$this определена (A) $this не определена. $this определена (B) $this не определена.
new
Для создания экземпляра класса используется директива new. Новый объект всегда будет создан, за исключением случаев, когда он содержит конструктор, в котором определен вызов исключения в случае ошибки. Рекомендуется определять классы до создания их экземпляров (в некоторых случаях это обязательно).
Если с директивой new используется строка ( string ), содержащая имя класса, то будет создан новый экземпляр этого класса. Если имя находится в пространстве имен, то оно должно быть задано полностью.
Пример #3 Создание экземпляра класса
// Это же можно сделать с помощью переменной:
$className = ‘Foo’ ;
$instance = new $className (); // Foo()
?>
В контексте класса можно создать новый объект через new self и new parent.
Когда происходит присвоение уже существующего экземпляра класса новой переменной, то эта переменная будет указывать на этот же экземпляр класса. Тоже самое происходит и при передаче экземпляра класса в функцию. Копию уже созданного объекта можно создать через ее клонирование.
Пример #4 Присваивание объекта
$instance = new SimpleClass ();
$assigned = $instance ;
$reference =& $instance ;
$instance -> var = ‘$assigned будет иметь это значение’ ;
$instance = null ; // $instance и $reference становятся null
var_dump ( $instance );
var_dump ( $reference );
var_dump ( $assigned );
?>
Результат выполнения данного примера:
NULL NULL object(SimpleClass)#1 (1) < ["var"]=>string(30) "$assigned будет иметь это значение" >
В PHP 5.3.0 введены несколько новых методов создания экземпляров объекта:
Пример #5 Создание новых объектов
class Test
static public function getNew ()
return new static;
>
>
?php
$obj1 = new Test ();
$obj2 = new $obj1 ;
var_dump ( $obj1 !== $obj2 );
$obj3 = Test :: getNew ();
var_dump ( $obj3 instanceof Test );
$obj4 = Child :: getNew ();
var_dump ( $obj4 instanceof Child );
?>
Результат выполнения данного примера:
bool(true) bool(true) bool(true)
extends
Класс может наследовать методы и свойства другого класса используя ключевое слово extends при его описании. Невозможно наследовать несколько классов, один класс может наследовать только один базовый класс.
Наследуемые методы и свойства могут быть переопределены (за исключением случаев, когда метод класса объявлен как final) путем объявления их с теми же именами, как и в родительском классе. Существует возможность доступа к переопределенным методам или статическим методам путем обращения к ним через parent::
Когда переопределяются методы число и типы аргументов должны оставаться такими же как и были, иначе PHP вызовет ошибку уровня E_STRICT . Это не относится к конструктору, который можно переопределить с другими параметрами.
Пример #6 Простое наследование классов
class ExtendClass extends SimpleClass
// Переопределение метода родителя
function displayVar ()
echo «Расширенный класс\n» ;
parent :: displayVar ();
>
>
?php
$extended = new ExtendClass ();
$extended -> displayVar ();
?>
Результат выполнения данного примера:
Расширенный класс значение по умолчанию
::class
Начиная с версии PHP 5.5 можно использовать ключевое слово class для разрешения имени класса. С помощью конструкции ClassName::class можно получить строку с абсолютным именем класса ClassName. Обычно это довольно полезно при работе с классами, использующими пространства имен.
Пример #7 Разрешение имени класса
Результат выполнения данного примера:
Объектно-ориентированное программирование
При создании программы на PHP и отдельных ее блоков нам вполне может хватить той функциональности, которую представляют функции. Однако PHP имеет и другие возможности по созданию программ, которые представляет объектно-ориентированное программирование. В ряде случаев программы, использующие ООП, проще в понимании, их легче поддерживать и изменять.
Ключевыми понятиями парадигмы ООП являются понятия «класс» и «объект». Описанием объекта является класс, а объект представляет экземпляр этого класса. Можно провести следующую аналогию: например, у каждого человека есть имя, определенный возраст, вес, какие-то другие параметры. То есть некоторый шаблон, который содержит набор параметров человека — этот шаблон можно назвать классом. А реально же существующий человек с конкретным именем, возрастом, весом и т.д. является объектом или экземпляром этого класса.
Для создания класса в PHP используется ключевое слово class , после которого идет название класса и фигурные скобки <> — блок кода класса. Например, новый класс, представляющий пользователя:
Чтобы создать объект класса Person, применяется ключевое слово new :
$person = new Person(); print_r($person); ?>
В данном случае переменная $person является объектом класса Person . С помощью функции print_r() можно вывести содержимое объекта, как и в случае с массивами.
При этом неважно, определяется класс до или после создания объекта. Например, мы можем сначала определить переменную класса, а потом определить этот класс:
Свойства и методы
Класс может содержать переменные, которые описывают какие-то признаки объекта, его состояние и которые еще назывют свойствами или атрибутам. И также класс класс может содержать функции, которые еще назвают методами и которые определяют его поведение.
Так, добавим в класс Person несколько свойств и методов:
"; > > $tom = new Person(); $tom->name = "Tom"; // установка свойства $name $tom->age = 36; // установка свойства $age $personName = $tom->name; // получение значения свойства $name echo "Имя пользователя: " . $personName . "
"; $tom->hello(); // вызов метода hello() print_r($tom); ?>
Здесь класс Person содержит два свойства: $name и $age . Свойства объявляются как обычные переменные, перед которыми стоит модификатор доступа — в данном случае модификатор public .
Методы представляют обычные функции, которые выполняют определенные действия. Здесь функция hello() просто выводит приветствие.
После создания объекта класса Person:
Мы можем через имя переменной класса обращаться к его свойствам и методам. Чтобы обратиться к свойствам и методам объекта применяется оператор доступа -> . Например, установить значения свойств:
$tom->name = "Tom"; // установка свойства $name $tom->age = 36; // установка свойства $age
Или получить значение (например, присвоить его переменной):
$personName = $tom->name; // получение значения свойства $name
Или вызвать методы объекта:
$tom->hello(); // вызов метода hello()
В итоге мы получим следующий вывод браузера:
Имя пользователя: Tom Hello! Person Object ( [name] => Tom [age] => 36 )
При этом свойствам можно задать в классе некоторые начальные значения:
"; > > $tom = new Person(); $tom->age = 36; // установка свойства $age echo "Имя пользователя: " . $tom->name . "
"; echo "Возраст пользователя: " . $tom->age . "
"; ?>
Имя пользователя: Undefined Возраст пользователя: 36
Ключевое слово this
Для обращения к свойствам и методам объекта внутри его класса применяется ключевое слово this . Например, определим в классе метод для вывода информации об объекте:
name ."; Age: " . $this->age . "
"; // также можно написать // echo "Name: $this->name; Age: $this->age
"; > > $tom = new Person(); $tom -> name = "Tom"; $tom -> displayInfo(); // Name: Tom; Age: 18 ?>
Для обращения к полям и методам внутри класса также применяется оператор доступа -> , перед которым идет $this . Причем это $this указывает именно на текущий объект. Что это значит в практическом плане? Например:
name; Age: $this->age
"; > > $tom = new Person(); $tom -> name = "Tom"; $tom -> displayInfo(); $bob = new Person(); $bob -> name = "Bob"; $bob -> age = 25; $bob -> displayInfo(); ?>
$this фактически будет указывать на переменную $tom . Тогда как при вызове
$this будет указывать на переменную $bob .
Name: Tom; Age: 18 Name: Bob; Age: 25
Сравнение объектов
При сравнении объектов классов следует принимать во внимание ряд особенностей. В частности, при использовании оператора равенства == два объекта считаются равными, если они представляют один и тот же класс и их свойства имеют одинаковые значения.
А при использовании оператора эквивалентности === оба объекта считаются равными, если обе переменных классах указывают на один и тот же экземпляр класса.
name; Age: $this->age
"; > > $tom = new Person(); $tom -> name = "Tom"; $tom -> age = 36; $tomas = new Person(); $tomas -> name = "Tom"; $tomas -> age = 36; if($tom == $tomas) echo "переменные tom и tomas равны
"; else echo "переменные tom и tomas НЕ равны
"; if($tom === $tomas) echo "переменные tom и tomas эквивалентны"; else echo "переменные tom и tomas НЕ эквивалентны"; ?>
Здесь сравниваются две переменных — $tom и $tomas. Они представляют один и тот же класс Person, и их свойства имеют одни и те же значения. Однако они представляют разные объекты. Поэтому при сравнении оператор == возвратит true , а оператор === — false :
переменные tom и tomas равны переменные tom и tomas НЕ эквивалентны
Возьмем другой пример, когда обе переменных представляют один и тот же объект:
$person = new Person(); $tom = $person; $tom -> name = "Tom"; $tom -> age = 36; $tomas = $person; if($tom == $tomas) echo "переменные tom и tomas равны
"; else echo "переменные tom и tomas НЕ равны
"; if($tom === $tomas) echo "переменные tom и tomas эквивалентны"; else echo "переменные tom и tomas НЕ эквивалентны";
Здесь объект класса Person создается только один раз: $person = new Person(); . И затем обе переменных $tom и $tomas будут указывать на этот объект. При этом не имеет значения, для какой именно переменной мы устанавливаем свойства. Так как в реальности это будет один и тот же объект. В итоге и оператор == , и оператор === при сравнении возвратят true
переменные tom и tomas равны переменные tom и tomas эквивалентны