Le 18/06/2021 à 18:08, Nikita Popov a écrit :
== comparison on objects is a == comparison on the properties. Whether the
properties are private doesn't (and shouldn't) matter.

Regards,
Nikita

Thanks a lot for your answer. This raises more question in my mind: I need to rephrase here.

My use case is the following, we have a custom identifier class in a project which does look like the code above:

<?php
use Ramsey\Uuid\UuidInterface;

interface Comparable
{
    public function equals(/* mixed */ $othjer): bool;
}

interface Identifier extends Comparable
{
}

interface UuidIdentifier implements Identifier
{
    public function getInternalUuid(): UuidIdentifier;
}

class FooId implements UuidIdentifier
{
    private UuidInterface $uuid;

    // Constructor doesn't matter here.

    public function getInternalUuid(): UuidIdentifier
    {
        return $this->uuid;
    }

    public function equals($other): bool
    {
        return $other instanceof UuidIdentifier && $this->uuid->equals($other->getInternalUuid());
    }
}
?>

Actually, use case is not exactly the same, but somehow looks like this.

Using the object equality, using `==` and `!=` some code of a colleague did work gracefully in unit tests, and in some other integration tests, but coverage did not reflect the real possible scenarios.

Fact is:

 - UuidInterface from ramsey/uuid is an opaque structure, that gives a contract but no guarantees about the internal reprensentation,  - it could be a LazyUuid, and Uuid4 or any other implementation, which all yield the same value, but not the same instance class,  - any UuidInterface instance could have been decorated and not be the same class name,  - all unit tests did build its objects using the same method, guaranting the same deep-equality, but the final application doesn't guarantee that all objects will be created the same way.

I spotted this during a review, and told him "that's weird, it should not work" and we had an infernal discussion until he found the https://www.php.net/manual/en/language.oop5.object-comparison.php page, but I finally dissuaded him to proceed this way and use the ->equals() method instead, which is an explicit and clear contract.

This implicit deep object equality in PHP could have caused some serious damage later in production, if, for any reason, we would have decorated some UuidInterface instances, or just instanciated those in many ways.

Wouldn't it be a good reason to implement an Equatable/Comparable interface in PHP, or a magic __compareTo() or __equals() method to allow us, in such scenario, to write a robust and predictible == and != behavior ?

This already existing RFC https://wiki.php.net/rfc/comparator_interface might not be the best one, but it's one to start with.

Regards,

--

Pierre

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to