Урок 01

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

Что такое ООП

ООП (объектно-ориентированное программирование) — парадигма, где программа строится из объектов, взаимодействующих друг с другом.

Объект — сущность с состоянием (данные) и поведением (методы).

Класс — чертёж объекта.

Аналогия

Класс — чертёж дома. Объект — конкретный дом.

Один чертёж — много домов.

Первый класс

class User
{
    public string $name;
    public int $age;

    public function greet(): string
    {
        return "Привет, я {$this->name}";
    }
}

Что здесь:

  • class User — объявление класса.
  • public string $name — свойство.
  • public function greet() — метод.
  • $this — ссылка на текущий объект.

Создание объекта

$user = new User();

$user->name = 'Иван';
$user->age = 25;

echo $user->greet();   // Привет, я Иван

new — создать экземпляр.

Свойства

Объявление:

class User
{
    public string $name;              // без значения
    public int $age = 0;              // со значением
    public ?string $email = null;     // nullable
    public array $roles = [];         // массив
}

Типизация обязательна (в современном PHP).

Обращение:

$user->name = 'Иван';
echo $user->name;

Методы

Функция внутри класса:

class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }
}

$calc = new Calculator();
echo $calc->add(2, 3);   // 5

$this — доступ к своим свойствам и методам:

class User
{
    public string $name;

    public function setName(string $name): void
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

$this — не переменная, а специальная ссылка.

Конструктор

Вызывается при new:

class User
{
    public function __construct(
        public string $name,
        public int $age,
    ) {}
}

$user = new User('Иван', 25);
echo $user->name;   // Иван

Constructor property promotion (PHP 8.0+) — свойства объявляются прямо в параметрах.

Старая запись

До 8.0:

class User
{
    public string $name;
    public int $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

Promotion короче в 3 раза.

Деструктор

Вызывается при уничтожении объекта:

class File
{
    private $handle;

    public function __construct(string $path)
    {
        $this->handle = fopen($path, 'r');
    }

    public function __destruct()
    {
        fclose($this->handle);
    }
}

Редко нужен — PHP сам чистит память (GC). Используется для освобождения ресурсов (файлы, сокеты).

Видимость

public — доступно везде:

public string $name;

protected — только внутри класса и наследников:

protected string $name;

private — только внутри класса:

private string $name;

Правило: по умолчанию — private, наружу — только нужное.

Пример с инкапсуляцией

class BankAccount
{
    private int $balance = 0;

    public function deposit(int $amount): void
    {
        if ($amount <= 0) {
            throw new InvalidArgumentException('Сумма должна быть положительной');
        }
        $this->balance += $amount;
    }

    public function withdraw(int $amount): void
    {
        if ($amount > $this->balance) {
            throw new RuntimeException('Недостаточно средств');
        }
        $this->balance -= $amount;
    }

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

$account = new BankAccount();
$account->deposit(1000);
$account->withdraw(300);

echo $account->getBalance();   // 700

$balance приватный — снаружи не изменить напрямую. Только через методы с проверками.

readonly

PHP 8.1+:

class User
{
    public function __construct(
        public readonly string $id,
        public readonly string $email,
    ) {}
}

$user = new User('1', 'ivan@example.com');
// $user->email = 'new@example.com';   // Error

Значение фиксируется после создания.

readonly class (8.2+)

Все свойства readonly:

readonly class Point
{
    public function __construct(
        public int $x,
        public int $y,
    ) {}
}

Статические свойства и методы

Свойства класса, не объекта:

class Counter
{
    private static int $count = 0;

    public static function increment(): void
    {
        self::$count++;
    }

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

Counter::increment();
Counter::increment();
echo Counter::get();   // 2

self:: — обращение внутри класса.

static:: — с учётом наследования.

⚠️ Статика — глобальное состояние. Используй осторожно.

Константы класса

class Status
{
    public const ACTIVE = 'active';
    public const PENDING = 'pending';
    private const INTERNAL = 'internal';
}

echo Status::ACTIVE;   // active

В PHP 8.1+ — enum лучше.

new с именованными аргументами

class User
{
    public function __construct(
        public string $name,
        public int $age,
        public bool $admin = false,
    ) {}
}

$user = new User(
    name: 'Иван',
    age: 25,
    admin: true,
);

Сравнение объектов

=== — тот же экземпляр:

$a = new User('Иван', 25);
$b = $a;

$a === $b;   // true

== — равны по свойствам:

$a = new User('Иван', 25);
$b = new User('Иван', 25);

$a == $b;    // true (одинаковые свойства)
$a === $b;   // false (разные объекты)

Клонирование

$a = new User('Иван', 25);
$b = clone $a;

$b->name = 'Пётр';
echo $a->name;   // Иван
echo $b->name;   // Пётр

Копия объекта — изменения независимы.

Для полной копии с вложенными объектами — __clone():

class Order
{
    public function __construct(
        public string $id,
        public Address $address,
    ) {}

    public function __clone()
    {
        $this->address = clone $this->address;
    }
}

Практика

<?php

declare(strict_types=1);

final class Product
{
    public function __construct(
        public readonly string $id,
        public readonly string $name,
        private int $price,
        private int $stock = 0,
    ) {}

    public function getPrice(): int
    {
        return $this->price;
    }

    public function setPrice(int $price): void
    {
        if ($price < 0) {
            throw new InvalidArgumentException('Цена не может быть отрицательной');
        }
        $this->price = $price;
    }

    public function isAvailable(): bool
    {
        return $this->stock > 0;
    }

    public function getTotal(int $qty): int
    {
        if ($qty > $this->stock) {
            throw new RuntimeException('Недостаточно товара');
        }
        return $this->price * $qty;
    }
}

$product = new Product('p1', 'iPhone', 100000, 10);

echo $product->getPrice();                          // 100000
echo $product->getTotal(2);                         // 200000
var_dump($product->isAvailable());                  // true

Итог

  • Класс — чертёж, объект — экземпляр.
  • public/protected/private — видимость.
  • $this — текущий объект.
  • __construct — при создании.
  • Promotion — короче.
  • readonly — иммутабельные свойства.
  • Статика — для утилит, но осторожно.
  • Инкапсуляция — приватные свойства + методы с проверками.

Дальше — свойства и методы.