Today I would like to talk about immutable objects in Object Oriented Programming.
As we all know, in OOP we operate with objects. In essence, everything is an object. But not in all programming languages. For example, in Java, a string is an object represented by the String class, and in PHP it is a collection of bytes represented as arrays. Every object has a behavior. For some objects, behavior can change the internal state of the object, for others it remains unchanged.
For example, PHP has 2 different classes: DateTime and DateTimeImmutable. The difference between objects of these two classes is that one can change its state and the other cannot.
When you want to decrease the date, you will always be working with a new object. For example:
public DateTimeImmutable::sub(DateInterval $interval): DateTimeImmutable
For the OOP world, immutable objects are much better than mutable ones. And that’s why. We are building a system of bricks, each object is a brick. When you have a mutable object, you are faced with dynamic behavior of the same object. Such objects are difficult to test. Their behavior can get out of control. It seemed to you that you changed the balance by 10 dollars on the 5th line of code, but as it turned out, this object had already been changed before! This generates a lot of hidden bugs. Therefore, in the Haskell programming language, all objects are immutable.
So let’s try to create an immutable object in PHP and see what we get.
<?php
declare(strict_types=1);
namespace App\Immutable;
final class Cash
{
/**
* @var int
*/
private int $dollars;
/**
* Cash constructor.
* @param int $dollars
*/
public function __construct(int $dollars)
{
$this->dollars = $dollars;
}
/**
* @param int $value
* @return Cash
*/
public function add(int $value): Cash
{
return new Cash($value + $this->dollars);
}
/**
* @return void
*/
public function printCurrentDollars(): void
{
printf("Object id: %d \t Dollars: %d \n", spl_object_id($this), $this->dollars);
}
}
Now let’s try to use the created class.
$tenDollars = new Cash(10);
$twentyDollars = $tenDollars->add(10);
$thirtyDollars = $twentyDollars->add(10);
$tenDollars->printCurrentDollars(); //Object id: 7568 Dollars: 10
$twentyDollars->printCurrentDollars(); //Object id: 7450 Dollars: 20
$thirtyDollars->printCurrentDollars(); //Object id: 4510 Dollars: 30
Every time the amount changes, a new object is returned to us. Thus, we always know what specific object we are dealing with and clearly control its behavior.
Immutable objects are easier to maintain and test!
Try to introduce this into your coding practice and the results will not be long in coming.