Sobes.tech
Middle

Значи ли това, че класът е непроменим, ако има публично свойство?

sobes.tech AI

Отговор от AI

Не.

Публичното свойство в клас означава, че стойността на това свойство може да бъде променена отвън на обекта. Непроменимият (immutable) обект е такъв, чийто статус (стойностите на свойствата му) не може да бъде променен след създаването. Наличието на публично свойство противоречи на принципа на неизменяемост.

За постигане на неизменяемост, класът трябва да отговаря на следните условия:

  • Всички свойства трябва да бъдат частни (private) или защитени (protected).
  • Не трябва да има сетъри (методи, които променят стойностите на свойствата).
  • Всички зависимости (обекти, с които работи класът) също трябва да бъдат неизменяеми или тяхното състояние не трябва да се променя отвън.
  • Конструкторът трябва да инициализира напълно обекта и той не трябва да се променя след създаването.
  • Ако са необходими промени, трябва да се създават нови екземпляри на обекта с новите стойности.

Пример за клас с публично свойство (променлив):

<?php
class MutableObject
{
    public $value; // Публично свойство

    public function __construct($value)
    {
        $this->value = $value;
    }
}

$obj = new MutableObject(10);
echo $obj->value; // 10

$obj->value = 20; // Стойността е променена отвън

echo $obj->value; // 20

Пример за реализиране на непроменим клас:

<?php
class ImmutableObject
{
    private $value; // Частно свойство

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function getValue() : int
    {
        return $this->value;
    }

    // Метод за "промяна", всъщност създава нов обект
    public function withValue(int $newValue) : self
    {
        return new self($newValue);
    }
}

$obj1 = new ImmutableObject(10);
echo $obj1->getValue(); // 10

// $obj1->value = 20; // Грешка: Не може да се достъпи частното свойство

$obj2 = $obj1->withValue(20); // Създава се нов обект

echo $obj1->getValue(); // 10 (оригиналният обект не се е променил)
echo $obj2->getValue(); // 20 (новият обект с променената стойност)