Объектно-ориентированное программирование в PHP
Объектно-ориентированное программирование (ООП) — популярная парадигма, основанная на использовании объектов для проектирования и разработки приложений.
Объектно-ориентированное программирование (ООП) — это способ структурирования кода вокруг объектов — самостоятельных единиц, объединяющих данные (называемые свойствами) и поведение, которое работает с этими данными (называемое методами). Вместо длинного списка функций, передающих данные туда-сюда, вы моделируете сущности своей предметной области (пользователя, заказ, подключение к базе данных) в виде объектов, и каждый из них сам управляет своим состоянием.
PHP поддерживает ООП начиная с PHP 5, а современные PHP-фреймворки — Laravel и Symfony — построены практически целиком на его основе. В этой главе объясняется, что такое ООП, зачем оно нужно и как ключевые идеи отображаются на синтаксис PHP. По окончании вы будете понимать разницу между классом и объектом и знать четыре основных принципа ООП: инкапсуляцию, наследование, полиморфизм и абстракцию.
Процедурный и объектно-ориентированный PHP
До появления классов PHP-код был, как правило, процедурным — последовательность инструкций и функций, работающих с обычными переменными:
$carMake = "Ford";
$carModel = "Mustang";
function describeCar($make, $model) {
return "The car is a $make $model.";
}
echo describeCar($carMake, $carModel);
// The car is a Ford Mustang.Это работает, но данные ($carMake, $carModel) и функция, которая их использует, связаны слабо. По мере роста проекта становится всё сложнее отслеживать, какие функции относятся к каким данным. ООП решает эту проблему, упаковывая данные и поведение вместе в один класс.
Классы и объекты
Два фундаментальных понятия в ООП — это класс и объект:
- Класс — это чертёж. Он описывает, какие свойства и методы будет иметь объект, но сам по себе не является значением, которое можно использовать напрямую — как архитектурный план дома.
- Объект — конкретный экземпляр, созданный по этому чертежу, с реальными заполненными значениями — как настоящий дом, построенный по плану.
В PHP класс объявляется с помощью ключевого слова class, а объект создаётся из него оператором new:
class Car {
public $make;
public $model;
}
$car = new Car(); // $car is an object (an instance of Car)
$car->make = "Ford";
$car->model = "Mustang";
echo $car->make; // FordИз одного класса можно создать сколько угодно независимых объектов, каждый из которых хранит собственную копию свойств. Оператор -> обращается к свойству или методу объекта. Подробнее см. в разделе Классы и объекты PHP.
Четыре принципа ООП
ООП строится на четырёх основных принципах. Для каждого из них в PHP есть соответствующая языковая конструкция.
Инкапсуляция
Инкапсуляция означает хранение данных объекта и методов, изменяющих их, в одном месте и контроль доступа извне. Помечая свойства как private и открывая их только через методы, вы защищаете объект от перевода в недопустимое состояние.
class BankAccount {
private $balance = 0;
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
}
}
public function getBalance() {
return $this->balance;
}
}
$account = new BankAccount();
$account->deposit(100);
echo $account->getBalance(); // 100Здесь $balance нельзя установить в бессмысленное значение напрямую — любое изменение проходит через deposit(), который проверяет входные данные.
Наследование
Наследование позволяет одному классу повторно использовать свойства и методы другого. Дочерний класс, объявленный с помощью extends, автоматически получает всё от родителя и может расширять или переопределять его. Это позволяет избежать дублирования общего кода. Подробности см. в разделе Наследование PHP.
class Vehicle {
public function start() {
return "Engine started.";
}
}
class Car extends Vehicle {
public function openTrunk() {
return "Trunk opened.";
}
}
$car = new Car();
echo $car->start(); // Engine started. (inherited)
echo $car->openTrunk(); // Trunk opened. (its own)Полиморфизм
Полиморфизм («многообразие форм») означает, что разные классы могут по-своему реагировать на один и тот же вызов метода. Код, вызывающий makeSound(), не должен знать, с кем работает — с Dog или с Cat:
class Dog {
public function makeSound() { return "Woof"; }
}
class Cat {
public function makeSound() { return "Meow"; }
}
foreach ([new Dog(), new Cat()] as $animal) {
echo $animal->makeSound() . "\n";
}
// Woof
// MeowПолиморфизм наиболее эффективен в сочетании с интерфейсами, которые гарантируют, что каждый класс предоставляет один и тот же набор методов.
Абстракция
Абстракция означает сокрытие деталей реализации за простым и чётко определённым интерфейсом. Пользователи класса работают с тем, что он делает, а не с тем, как он это делает. PHP поддерживает это через абстрактные классы и интерфейсы, которые определяют сигнатуры методов без реализации (или с частичной реализацией).
Всё вместе: полный пример
Класс ниже объединяет свойства, конструктор, который запускается автоматически при создании объекта, и метод:
class Car {
public $color;
public $make;
public $model;
function __construct($color, $make, $model) {
$this->color = $color;
$this->make = $make;
$this->model = $model;
}
function getDescription() {
return "The car is a " . $this->make . " " . $this->model . " in " . $this->color . " color.";
}
}
$car = new Car("red", "Ford", "Mustang");
echo $car->getDescription();
// The car is a Ford Mustang in red color.Что здесь происходит:
- Класс
Carобъявляет три публичных свойства —color,makeиmodel. __construct()— это специальный метод, который PHP вызывает в момент выполненияnew Car(...). Он копирует аргументы в свойства объекта с помощью$this, который всегда указывает на текущий объект.getDescription()читает эти свойства и возвращает строку.new Car("red", "Ford", "Mustang")создаёт объект; вызов$car->getDescription()выводит результат, показанный в комментарии.
Когда следует использовать ООП?
ООП особенно эффективно, когда приложение содержит множество связанных сущностей с собственными данными и поведением, когда нужно повторно использовать код в рамках проекта или когда вы работаете с фреймворком, который его ожидает. Для небольшого одноразового скрипта обычные процедурные функции могут оказаться проще. Большинство реального PHP-кода — API, веб-приложения, библиотеки — опирается на ООП, потому что оно помогает поддерживать порядок и тестируемость в растущих кодовых базах.
Заключение
Объектно-ориентированное программирование организует код вокруг объектов, объединяющих данные с поведением. Вы определяете класс как чертёж и создаёте объекты из него с помощью new. Четыре принципа — инкапсуляция, наследование, полиморфизм и абстракция — дают инструменты для защиты данных, повторного использования кода и сохранения управляемости крупных приложений.
Чтобы углубиться в тему, продолжите с Классов и объектов PHP, затем изучите наследование, интерфейсы, абстрактные классы и трейты.