Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Инкапсуляция PHP: Введение в ООП

В общепринятом ООП есть один термин, которым любят пугать новичков. Имя ему — инкапсуляция.

В первой части этого курса мы строили абстракции, используя обычные функции с применением подхода data hiding.

<?php

$point = makeDecartPoint(3, 4);
getX($point); // 3
getY($point); // 4

В объектно-ориентированном подходе функции объединяются с данными и описываются вместе внутри класса (в классово-ориентированных языках). Инкапсуляция — механизм, позволяющий описывать данные и функции, оперирующие ими, в рамках одной языковой конструкции. В случае PHP такой конструкцией является класс.

Мы уже начали так делать, когда знакомились с конструктором. Такие функции принято именовать методами, так как они связаны с объектом, на котором вызываются. Визуально вызов метода выглядит как обращение к свойству и его вызов.

<?php

$point = new Point(3, 4);
$point->getX(); // 3
$point->getY(); // 4

Вызов метода не требует передачи объекта в аргументах, потому что метод вызывается на объекте и имеет к нему доступ через переменную $this.

<?php

class Point
{
    public $x;
    public $y;

    public function __construct($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }
}

Методы, которые извлекают составные части объекта, принято называть геттерами (getters), а методы, изменяющие составные части — сеттерами (setters). Как правило, геттеры и сеттеры один в один отображаются на конкретные свойства внутри объекта. Технически методы — обычные функции, за исключением доступа к $this и способа вызова.

<?php

class Point
{
    public $x;
    public $y;

    public function __construct($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }

    public function setX($x)
    {
        $this->x = $x;
    }

    public function setY($y)
    {
        $this->y = $y;
    }
}

$point = new Point(5, 10);
$point->setX(100);
print_r($point->getX()); // => 100

Сеттеры в примере выше показаны только для демонстрации. В реальном коде точка почти наверняка будет неизменяемым объектом.

Но геттеры и сеттеры — не единственные типы функций, которые позволяют описывать класс. В принципе, всё, что мы описывали, работая без классов, с таким же успехом описывается и с классами.

Реализация без классов:

<?php

function distanceTo($point1, $point2)
{

    $squareOfX = (getX($point1)  getX($point2)) ** 2;
    $squareOfY = (getY($point1)  getY($point2)) ** 2;

    return sqrt($squareOfY + $squareOfX);
}

Реализация в классе:

<?php

class Point
{
    ...

    /*
     * Расчет по теореме Пифагора связи между
     * сторонами прямоугольного треугольника с^2 = a^2 + b^2
    */
    public function distanceTo($point)
    {
        $squareOfX = ($this->getX()  $point->getX()) ** 2;
        $squareOfY = ($this->getY()  $point->getY()) ** 2;

        return sqrt($squareOfY + $squareOfX);
    }
}

$point1 = new Point(0, 0);
$point2 = new Point(3, 4);
print_r($point1->distanceTo($point2)); // => 5
print_r($point2->distanceTo($point1)); // => 5

Данная операция обладает свойством коммутативности: результат вычисления не зависит от того, в каком порядке идут аргументы. Соответственно, при использовании методов, можно вызывать distanceTo как на одном объекте, так и на другом.

Нередко методы выполняют не только вычисления, но и возвращают новые объекты. Например, так произойдёт при вычислении симметричной точки.

<?php

class Point
{
    // ...

    public function getSymmetricalPoint()
    {
        // Можно выполнять промежуточное создание переменной, а можно возвращать сразу
        return new Point(-$this->getX(), -$this->getY());
    }
}

$point = new Point(3, 8);
$point->getSymmetricalPoint(); // => (-3, -8)

Выше мы рассмотрели техническую сторону вопроса, оставив за кадром описание преимуществ и недостатков такого подхода, а также связанные темы, например, data hiding или полиморфизм. Их описание довольно обширно и практически бесполезно без хотя бы минимального опыта использования. О том, что даёт или забирает инкапсуляция, мы поговорим на протяжении ближайших уроков. Отдельного обсуждения заслуживает вопрос о способе хранения методов — где они находятся физически (внутри объекта или нет?). С ним мы разберёмся в уроках, посвящённых полиморфизму и динамической диспетчеризации.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка веб-приложений на Laravel
10 месяцев
с нуля
Старт 28 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»