← Назад к вопросам

Означает ли иммутабельность если в классе есть публичное свойство?

3.0 Senior🔥 62 комментариев
#PHP Core#ООП

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Означает ли публичное свойство нарушение иммутабельности?

Нет, само по себе наличие публичного свойства (public) в классе не означает автоматически нарушение иммутабельности. Ключевой вопрос — можно ли изменить состояние объекта после его создания. Иммутабельность — это свойство объекта, а не отдельного поля. Объект считается иммутабельным, если его состояние невозможно изменить после инстанцирования.

Как достигается иммутабельность с публичными свойствами

Даже при публичных свойствах объект может оставаться иммутабельным, если соблюдены определенные условия:

1. Свойство объявлено как readonly (PHP 8.1+)

Это наиболее чистый современный способ. Инициализировать такое свойство можно только в конструкторе.

final class ImmutablePoint {
    public readonly int $x;
    public readonly int $y;
    
    public function __construct(int $x, int $y) {
        $this->x = $x;
        $this->y = $y;
    }
}
// Попытка изменения вызовет Fatal error
$point = new ImmutablePoint(5, 10);
// $point->x = 20; // ОШИБКА: Cannot modify readonly property

2. Отсутствие сеттеров и модифицирующих методов

Даже с публичными свойствами, если нет методов, меняющих их значения, и свойства не перезаписываются извне (через Reflection или магию), объект де-факто иммутабелен.

class ImmutableValue {
    public string $value;
    
    public function __construct(string $value) {
        $this->value = $value;
    }
    
    // Нет методов типа setValue() или changeValue()
}
// Технически возможно, но не предполагается по дизайну:
$obj = new ImmutableValue('test');
// $obj->value = 'new'; // Возможно, но нарушает контракт класса

3. Возврат нового объекта при операциях

Классический паттерн — методы типа withX() возвращают новый экземпляр вместо изменения текущего.

final class ImmutableMoney {
    public float $amount;
    public string $currency;
    
    public function __construct(float $amount, string $currency) {
        $this->amount = $amount;
        $this->currency = strtoupper($currency);
    }
    
    public function add(float $amount): self {
        return new self($this->amount + $amount, $this->currency);
    }
}
$money = new ImmutableMoney(100, 'USD');
$newMoney = $money->add(50); // Новый объект, старый не изменен

Когда публичные свойства делают объект мутабельным

Объект становится мутабельным, если его публичные свойства можно изменить напрямую после создания:

class MutablePoint {
    public int $x;
    public int $y;
}
$point = new MutablePoint();
$point->x = 5; // Прямое изменение — мутабельность

Рекомендации по проектированию иммутабельных классов

  • Используйте readonly свойства для явной гарантии иммутабельности.
  • Объявляйте класс final чтобы предотвратить наследование с добавлением мутабельного состояния.
  • Защищайте внутренние объекты: если свойство содержит объект, убедитесь, что он тоже иммутабелен или возвращайте его копию.
  • Для сложных объектов лучше использовать приватные свойства с публичными геттерами:
    final class ImmutableUser {
        private string $name;
        private DateTimeImmutable $createdAt;
        
        public function __construct(string $name, DateTimeImmutable $createdAt) {
            $this->name = $name;
            $this->createdAt = $createdAt;
        }
        
        public function getName(): string { return $this->name; }
        
        public function getCreatedAt(): DateTimeImmutable { 
            return $this->createdAt; // DateTimeImmutable сам по себе иммутабелен
        }
    }
    

Вывод

Иммутабельность определяется не видимостью свойств, а невозможностью изменить состояние объекта после создания. Публичные свойства могут быть частью иммутабельного дизайна при использовании readonly, отсутствии сеттеров и возврате новых объектов при операциях. Однако на практике для надежной иммутабельности рекомендуется комбинация: private/protected свойства + геттеры + readonly + final класс + использование иммутабельных типов для вложенных объектов.

Означает ли иммутабельность если в классе есть публичное свойство? | PrepBro