Equatable
Tells whether an object is equal to other value.
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. The library contains two types that implement this interface: Result
and Option
. Also, to ease dealing with the Equatable
types the library defines several functions.
/** @implements Equatable<Phone> */
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.
/**
* @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 ourequals()
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 theEquatable
interface. Who knows, maybe even generics (RFC) will be implemented in very close future. With the phpdoc version, it'll be possible to adapt it, without breaking other people's code.
Last updated