PHP классы: от простого объявления до современных подходов
Определение класса и его базовые элементы
Класс в PHP представляет собой шаблон для создания объектов. Он объединяет данные (свойства) и функции (методы).
Пример простейшего класса:
<?php
class User {
public string $name;
public int $age;
public function greet(): string {
return "Привет, меня зовут {$this->name}";
}
}
$user = new User();
$user->name = 'Анна';
$user->age = 25;
echo $user->greet();
?>Php какой класс (классы в php)
Привет, меня зовут Анна
После объявления класса можно создавать экземпляры с помощью new. Свойствам присваиваются значения, затем вызываются методы.
Почему возникает ошибка "Undefined property"?
При обращении к необъявленному свойству PHP создаст динамическое свойство (в старых версиях) или вызовет ошибку. Чтобы избежать этого, всегда объявляйте свойства с модификаторами доступа.
Как объявить свойства с разной областью видимости?
Модификаторы доступа: public, protected, private.
<?php
class BankAccount {
public string $owner;
protected float $balance = 0.0;
private string $pin = '1234';
public function deposit(float $amount): void {
$this->balance += $amount;
}
public function getBalance(): float {
return $this->balance;
}
}
$acc = new BankAccount();
$acc->owner = 'Иван'; // public – доступно
// $acc->balance = 500; // Ошибка: protected
// echo $acc->pin; // Ошибка: private
$acc->deposit(1000);
echo $acc->getBalance(); // 1000
?>
Почему прямое изменение свойства извне запрещено?
Инкапсуляция защищает внутреннее состояние объекта. Для изменения закрытых свойств используются публичные методы, которые могут проверять входные данные или выполнять дополнительную логику.
Как использовать конструктор для инициализации объекта?
Метод __construct вызывается автоматически при создании экземпляра.
<?php
class Product {
public function __construct(
public string $name,
public float $price
) {}
public function getInfo(): string {
return "{$this->name}: {$this->price} руб.";
}
}
$phone = new Product('Смартфон', 29999.99);
echo $phone->getInfo();
?>
Смартфон: 29999.99 руб.
Конструктор с продвижением свойств (constructor promotion) – удобный способ объявить и сразу заполнить свойства.
Когда нужны статические свойства и методы?
Статические члены принадлежат классу, а не объекту. Они доступны через ::.
<?php
class Counter {
private static int $count = 0;
public static function increment(): void {
self::$count++;
}
public static function getCount(): int {
return self::$count;
}
}
Counter::increment();
Counter::increment();
echo Counter::getCount(); // 2
?>
Что произойдет при попытке вызвать статический метод через объект?
Это разрешено, но не рекомендуется, так как может ввести в заблуждение. Статические методы следует вызывать через имя класса.
Расширенные примеры работы с классами
Ниже приведены более сложные сценарии: использование интерфейсов, абстрактных классов, трейтов и современных возможностей PHP.
Как реализовать интерфейс?
<?php
interface Drawable {
public function draw(): string;
}
class Circle implements Drawable {
public function __construct(private float $radius) {}
public function draw(): string {
return "Круг с радиусом {$this->radius}";
}
}
class Square implements Drawable {
public function __construct(private float $side) {}
public function draw(): string {
return "Квадрат со стороной {$this->side}";
}
}
function render(Drawable $shape): void {
echo $shape->draw() . "\n";
}
render(new Circle(5));
render(new Square(10));
?>
Круг с радиусом 5 Квадрат со стороной 10
Интерфейсы гарантируют, что классы реализуют определённые методы.
Как наследовать и переопределять методы?
<?php
class Animal {
public function __construct(protected string $name) {}
public function sound(): string {
return "Издаёт звук";
}
}
class Dog extends Animal {
public function sound(): string {
return "{$this->name} лает: Гав-гав!";
}
}
class Cat extends Animal {
public function sound(): string {
return "{$this->name} мяукает: Мяу!";
}
}
$dog = new Dog('Рекс');
echo $dog->sound() . "\n";
$cat = new Cat('Мурка');
echo $cat->sound();
?>
Рекс лает: Гав-гав! Мурка мяукает: Мяу!
Наследование позволяет расширить или изменить поведение родительского класса.
Как использовать трейты для повторного использования кода?
<?php
trait Logger {
public function log(string $message): void {
echo "[LOG] $message\n";
}
}
trait Timestamp {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
class Application {
use Logger, Timestamp;
public function run(): void {
$this->log('Приложение запущено в ' . $this->getTimestamp());
}
}
$app = new Application();
$app->run();
?>
[LOG] Приложение запущено в 2025-03-10 15:30:45
Трейты решают проблему множественного наследования и позволяют добавлять методы в любой класс.
Как использовать readonly свойства (PHP 8.1+)
<?php
class Point {
public function __construct(
public readonly float $x,
public readonly float $y
) {}
}
$p = new Point(3.5, 7.2);
echo "({$p->x}, {$p->y})";
// $p->x = 10; // Ошибка: нельзя изменить readonly свойство
?>
(3.5, 7.2)
Readonly свойства устанавливаются один раз (в конструкторе) и затем неизменны.
Как создать абстрактный класс?
<?php
abstract class Shape {
abstract public function area(): float;
public function describe(): string {
return "Фигура площадью " . $this->area();
}
}
class Rectangle extends Shape {
public function __construct(private float $width, private float $height) {}
public function area(): float {
return $this->width * $this->height;
}
}
$rect = new Rectangle(4, 5);
echo $rect->describe();
?>
Фигура площадью 20
Абстрактные классы не могут быть инстанциированы напрямую, они задают общий интерфейс для дочерних классов.