Объявление класса
<?php
declare(strict_types=1);
class User
{
// Properties (attributes)
public string $name;
public int $age;
protected string $email;
private string $password;
// Constructor
public function __construct(string $name, int $age, string $email, string $password)
{
$this->name = $name;
$this->age = $age;
$this->email = $email;
$this->password = $password;
}
// Method
public function greet(): string
{
return "Hello, I'm {$this->name}, {$this->age} years old";
}
// Getter for protected property
public function getEmail(): string
{
return $this->email;
}
}
// Creating objects
$user = new User('Alice', 25, '[email protected]', 'secret');
echo $user->greet(); // Hello, I'm Alice, 25 years old
echo $user->name; // Alice (public — accessible)
// echo $user->password; // Fatal error (private)
Модификаторы видимости (Visibility)
| Модификатор | Класс | Наследники | Извне |
|---|---|---|---|
public |
Да | Да | Да |
protected |
Да | Да | Нет |
private |
Да | Нет | Нет |
<?php
declare(strict_types=1);
class Account
{
public string $holder = 'John'; // Accessible everywhere
protected float $balance = 0.0; // Class + children only
private string $pin = '1234'; // This class only
public function deposit(float $amount): void
{
$this->balance += $amount; // OK — same class
$this->validatePin(); // OK — same class
}
private function validatePin(): bool
{
return strlen($this->pin) === 4;
}
}
class SavingsAccount extends Account
{
public function getBalance(): float
{
return $this->balance; // OK — protected accessible in child
// return $this->pin; // ERROR — private not accessible in child!
}
}
$account = new Account();
echo $account->holder; // OK — public
// echo $account->balance; // Fatal error — protected
// echo $account->pin; // Fatal error — private
Ловушка экзамена:
privateсвойства и методы недоступны в дочерних классах.protected— доступны в самом классе и его наследниках, но НЕ извне. Метод, объявленный какprivate, можно "переопределить" в дочернем классе, но это будет НОВЫЙ метод (не override).
Свойства
<?php
declare(strict_types=1);
class Product
{
// Typed properties (PHP 7.4+)
public string $name;
public float $price;
public ?string $description = null; // Nullable with default
// Default values
public int $quantity = 0;
public array $tags = [];
public bool $active = true;
// Readonly (PHP 8.1+)
public readonly string $sku;
// Static properties
public static int $instanceCount = 0;
public function __construct(string $name, float $price, string $sku)
{
$this->name = $name;
$this->price = $price;
$this->sku = $sku;
self::$instanceCount++;
}
}
$p = new Product('Widget', 9.99, 'WDG-001');
echo $p->name; // Widget
echo Product::$instanceCount; // 1
// readonly — can only be set once
// $p->sku = 'NEW'; // Error: Cannot modify readonly property
Запомни: Типизированное свойство без значения по умолчанию находится в "неинициализированном" состоянии. Обращение к такому свойству до инициализации вызовет
Error: Typed property must not be accessed before initialization.
Статические свойства и методы
<?php
declare(strict_types=1);
class Counter
{
private static int $count = 0;
public static function increment(): void
{
self::$count++;
}
public static function getCount(): int
{
return self::$count;
}
public function instanceMethod(): void
{
// Can access static from instance method
echo self::$count;
echo static::$count; // Late static binding
}
}
Counter::increment();
Counter::increment();
echo Counter::getCount(); // 2
// Static methods cannot use $this!
// $this refers to an instance, static has no instance
Константы класса
<?php
declare(strict_types=1);
class HttpStatus
{
public const OK = 200;
public const NOT_FOUND = 404;
public const SERVER_ERROR = 500;
// Typed constants (PHP 8.3+)
public const string VERSION = '1.0';
// Visibility on constants (PHP 7.1+)
protected const SECRET_KEY = 'abc123';
private const INTERNAL_VERSION = 42;
}
echo HttpStatus::OK; // 200
echo HttpStatus::NOT_FOUND; // 404
// Access via instance
$status = new HttpStatus();
echo $status::OK; // 200
// Dynamic access
$class = HttpStatus::class;
echo $class::OK; // 200
echo constant('HttpStatus::OK'); // 200
Создание и клонирование объектов
<?php
declare(strict_types=1);
class Config
{
public array $settings = [];
public function __construct(array $settings)
{
$this->settings = $settings;
}
}
$config1 = new Config(['debug' => true]);
// Assignment copies the object HANDLE (not the object itself)
$config2 = $config1;
$config2->settings['debug'] = false;
echo $config1->settings['debug'] ? 'true' : 'false'; // false — SAME object!
// Clone creates a SHALLOW copy
$config3 = clone $config1;
$config3->settings['debug'] = true;
echo $config1->settings['debug'] ? 'true' : 'false'; // true — different object!
// But nested objects are still shared (shallow copy)!
Ловушка экзамена: Присваивание объекта (
$b = $a) копирует ИДЕНТИФИКАТОР, а не объект. Оба указывают на один объект.cloneсоздаёт ПОВЕРХНОСТНУЮ копию: скалярные свойства копируются, но объекты внутри остаются общими. Для глубокого копирования реализуйте__clone().
Анонимные классы (PHP 7.0+)
<?php
declare(strict_types=1);
// Anonymous class
$logger = new class {
public function log(string $message): void
{
echo "[LOG] {$message}\n";
}
};
$logger->log('Test'); // [LOG] Test
// With constructor and interface
interface LoggerInterface {
public function log(string $message): void;
}
function createLogger(string $prefix): LoggerInterface
{
return new class($prefix) implements LoggerInterface {
public function __construct(private readonly string $prefix) {}
public function log(string $message): void
{
echo "[{$this->prefix}] {$message}\n";
}
};
}
$logger = createLogger('APP');
$logger->log('Started'); // [APP] Started