Классы и объекты
Что такое ООП
ООП (объектно-ориентированное программирование) — парадигма, где программа строится из объектов, взаимодействующих друг с другом.
Объект — сущность с состоянием (данные) и поведением (методы).
Класс — чертёж объекта.
Аналогия
Класс — чертёж дома. Объект — конкретный дом.
Один чертёж — много домов.
Первый класс
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— иммутабельные свойства.- Статика — для утилит, но осторожно.
- Инкапсуляция — приватные свойства + методы с проверками.
Дальше — свойства и методы.