# Equatable

## Overview

Normally, to compare objects you'd use the comparison operator `==` or the identical operator `===`. Sometimes it can do the job, but most of the time it's not enough. In some cases, we'd like to control the way our object is compared. It'd be great if PHP allowed for operator overloading, but unfortunately, at the moment it's not possible. This is one of the main reasons why the type `Equatable` exist.

Types that implement the `Equatable<T>` interface can be compared for equality to other value using the `equals()` method. Thanks to the fact the `Equatable` type is a generic interface, you can decide to what type your object can be compared.

It can become very useful when designing eg. value objects. To ease dealing with the `Equatable` types the library defines several [functions](https://piku235.gitbook.io/jungi-common/functions).

```php
/** @implements Equatable<self> */
class Phone implements Equatable
{
    public function __construct(private string $value) {}
    
    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }
}

assert(true === (new Phone('(321) 456-1234'))->equals(new Phone('(321) 456-1234')));
assert(false === (new Phone('(321) 456-1234'))->equals(new Phone('(454) 456-1234')));
```

## Design decisions

Technically, the `Equatable` interface doesn't contain any method. The `equals()` method was defined using the phpdoc  `@method` tag. I also was considering an alternative version, but in the end I stuck to the phpdoc version. I'll show you and try to explain why I prefer the phpdoc version over this alternative one.

```php
/**
 * @template T
 */
interface Equatable
{
    /** 
     * @param T $other
     */
    public function equals($other): bool;
}
```

At first glance, it looks better, but:

* Types of this interface would be forced to accept a value of any type. Of course, we can specify a parameter type using the `@param` tag, but we'd need to always remember about it. PHP at runtime won't care if something was incorrectly passed to our `equals()` method, it'll simply allow it, thus we lose the runtime type check.
* The `equals()` method is locked for any API changes. In future PHP versions, there may be means to better express the `Equatable` interface. Who knows, maybe even generics ([RFC](https://wiki.php.net/rfc/generics)) will be implemented in very close future. With the phpdoc version, it'll be possible to adapt it, without breaking other people's code.
