W3docs

Объектно-ориентированное программирование в 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, затем изучите наследование, интерфейсы, абстрактные классы и трейты.

Практика

Практика
Какова функция объектно-ориентированного программирования (ООП) в PHP?
Какова функция объектно-ориентированного программирования (ООП) в PHP?
Was this page helpful?