Перейти к содержанию
Educora
Средний18 мин6 / 10

Классы и объекты

Создавай классы, используй продвижение свойств в конструкторе (constructor promotion) и readonly-свойства, изучи статические члены и наследование.

Проверь себя
В этом уроке ты узнаешь
  • Писать класс со свойствами и методами и создавать объекты через new
  • Применять продвижение свойств в конструкторе, readonly и уровни видимости
  • Использовать статические члены и наследование через extends

У банковского счёта есть владелец и баланс; на счёт можно положить деньги и проверить баланс. Чтобы хранить данные и функции для работы с ними в одном месте, используют объектно-ориентированное программирование (ООП). Современные PHP-фреймворки, такие как Laravel и Symfony, целиком построены на классах, поэтому эта тема — основа профессиональной работы с PHP.

Класс и объект

Класс — это чертёж объектов: он описывает, какие у них будут свойства (данные) и методы (действия). Объект — конкретный экземпляр класса, созданный через new. Внутри метода $this указывает на текущий объект, а к свойствам и методам обращаются через оператор ->. Метод __construct вызывается автоматически в момент создания объекта.

PHP
<?php

class Account
{
    public string $owner;
    private float $balance = 0.0;

    public function __construct(string $owner)
    {
        $this->owner = $owner;
    }

    public function deposit(float $amount): void
    {
        $this->balance += $amount;
    }

    public function getBalance(): float
    {
        return $this->balance;
    }
}

$acc = new Account("Aysel");
$acc->deposit(50);
$acc->deposit(25.5);
echo $acc->owner, ": ", $acc->getBalance(), " AZN\n";
Ожидаемый результат
Aysel: 75.5 AZN
ВидимостьОткуда доступно
publicотовсюду
protectedиз самого класса и его классов-наследников
privateтолько из самого класса
Если написать $acc->balance, получишь ошибку Cannot access private property — баланс меняется только через методы.

Продвижение свойств и readonly

В классе выше $owner написан трижды: как свойство, как параметр и в присваивании. С продвижением свойств в конструкторе (constructor promotion) из PHP 8 ты пишешь модификатор видимости прямо у параметра конструктора — PHP сам объявит свойство и присвоит значение.

Стиль PHP 7
class Product
{
    private string $name;
    private float $price;

    public function __construct(string $name, float $price)
    {
        $this->name = $name;
        $this->price = $price;
    }
}
PHP 8: продвижение свойств
class Product
{
    public function __construct(
        private string $name,
        private float $price,
    ) {}
}
Оба класса делают одно и то же, но правый вдвое короче.

Начиная с PHP 8.1 свойство можно объявить **readonly**: значение ему присваивается только один раз, внутри класса. Если потом попытаться его изменить, получишь ошибку Cannot modify readonly property Money::$amount. Такие неизменяемые объекты идеально подходят для денег, дат и координат. Ниже мы храним деньги в гяпиках как целое число (1 манат = 100 гяпиков).

PHP
<?php

final class Money
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency = "AZN",
    ) {}

    public function add(Money $other): Money
    {
        return new Money($this->amount + $other->amount, $this->currency);
    }

    public function __toString(): string
    {
        return number_format($this->amount / 100, 2) . " " . $this->currency;
    }
}

$price = new Money(1250);
$total = $price->add(new Money(799));
echo $total, "\n";
echo $total->amount, "\n";
Ожидаемый результат
20.49 AZN
2049
  • add не меняет старый объект, а возвращает новый объект Money — так работают неизменяемые объекты.
  • Специальный метод __toString превращает объект в строку, поэтому работает echo $total.
  • final запрещает создавать классы-наследники от этого класса.

Статические члены

Статические свойства и методы принадлежат не отдельному объекту, а всему классу. К ним обращаются через ИмяКласса::член, а изнутри класса — через self::. Константы класса (const) читаются так же. Ниже класс считает, сколько объектов-учеников было создано.

PHP
<?php

class Student
{
    public const MAX_IN_CLASS = 30;
    private static int $count = 0;

    public function __construct(public string $name)
    {
        self::$count++;
    }

    public static function count(): int
    {
        return self::$count;
    }
}

new Student("Leyla");
new Student("Murad");
$s = new Student("Nigar");

echo Student::count(), " of ", Student::MAX_IN_CLASS, "\n";
echo $s->name, "\n";
Ожидаемый результат
3 of 30
Nigar

Наследование

С помощью ключевого слова extends класс наследует все public- и protected-члены другого класса и может переопределить (override) любые его методы. К методу родителя обращаются через parent::. В PHP у класса может быть только один родитель. Когда один и тот же метод по-разному работает в разных классах, это называют полиморфизмом.

PHP
<?php

class Animal
{
    public function __construct(protected string $name) {}

    public function speak(): string
    {
        return "{$this->name} makes a sound";
    }
}

class Cat extends Animal
{
    public function speak(): string
    {
        return "{$this->name} says Meow";
    }
}

class Dog extends Animal
{
    public function speak(): string
    {
        return parent::speak() . ": Woof!";
    }
}

$pets = [new Animal("Fish"), new Cat("Mestan"), new Dog("Bobik")];
foreach ($pets as $pet) {
    echo $pet->speak(), "\n";
}
Ожидаемый результат
Fish makes a sound
Mestan says Meow
Bobik makes a sound: Woof!

Главное

  • Класс — чертёж, объект — его экземпляр, созданный через new; $this означает текущий объект, а -> — обращение к члену.
  • public, protected и private определяют, откуда видны члены; храни данные private и изменяй их через методы.
  • Продвижение свойств (PHP 8) объявляет свойства прямо в параметрах конструктора; readonly (PHP 8.1) делает свойство неизменяемым.
  • Статические члены принадлежат классу и читаются через self:: или ИмяКласса::.
  • extends создаёт наследование, parent:: вызывает метод родителя, а final запрещает наследование.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
На что указывает $this внутри метода?