php-enum: Missing equalTo() method

Sometimes i want to compare enums for equaility, currnetly i have to cast to (string) to make it work. This could be something to add as a default method.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 30 (19 by maintainers)

Most upvoted comments

@mnapoli @jeremykendall My team and I use this library as a base for our own enum library (a wrapper, you can call it) and we tend to add features that seems necessary for us and maybe doesn’t warrant the inclusion to php-enum itself. With that intro, I’ll share our insights cause we’ve discussed “equals in php” problem couple of times:

The need for equals method is most visible to (ex-)Java programmers who wander to php valley. I consider Java functionality of comparing objects a good mechanism and is considered so by Java community in general (afaik, never seen people complaining). I’m talking about equals + hashCode flexibility. This post provides an easy walkthrough on functionality. See this question as an exactly the same question we have here, just in Java world.

The beauty there is “equals defers to ==”. That means, if you don’t override it, both will work the same way. Also, Java internals use equals method to compare objects which means you can change it’s done by overriding equals or hashCode (the latter being the blessed way).

Back to PHP, that’s not how it works. PHP internals will almost always use ==. So what? Indeed, there is no difference in standard case:

final class Color extends \MyCLabs\Enum\Enum {
    const RED = 'red';
    const BLUE = 'blue';
}

$red = COLOR::RED();
$blue = COLOR::BLUE();

$anotherRed = COLOR::RED();

// Equality check using == // expected
var_dump($red == $red); // true
var_dump($red == $blue); // false
var_dump($red == $anotherRed); // true

// Equality check using equals() // expected
var_dump($red->equals($red)); // true
var_dump($red->equals($blue)); // false
var_dump($red->equals($anotherRed)); // true

All good, there is no blessed equality checking method, user uses whichever preferred.

Then, user goes and overwrites the equal method (“because reasons”) and both methods stop producing the same results. Having that, it’s a matter of time for bugs to start cropping in cause the user is accustomed to using both method interchangeably.

There is a simple fix which would make the design of that feature better - declare the equals method final. That way, you can’t simply extend this library, make mess and blame the library - if you want some flexibility and you know what you’re doing - go with composition.

Maybe I’m being picky now, but that’s what I expect from a good enum library in php if it introduces a third way of comparing objects. Not only enum library, the same goes for value objects.

btw. another way of solving that is going full-Java:

abstract class JavaLikeEnum extends \MyCLabs\Enum\Enum {
    final public function equals(\MyCLabs\Enum\Enum $outsider)
    {
        return $this->hashCode() == $outsider->hashCode();
    }

    protected function hashCode() {
        return $this->getValue();
    }
}

if you want to change what equals means, go after hashCode, don’t touch equals. Anyhow, both your method and the one I proposed bring an additional comparison method that bring no added functionality, just confusion in the long run.

+1 for a ‘equalsTo’ method. It’s much easier to use.

public function equalsTo($enum)
{
  return $this == $enum;
}
$enum1 = Enum::KEY_ONE();
$enum2 = Enum::KEY_TWO();

$enum1->equalsTo($enum2); (false)
$enum1->equalsTo($enum1); (true)

MINOR version when you add functionality in a backwards-compatible manner

That’s the issue, it wasn’t added in a backwards compatible manner.

Cannot override final method MyCLabs\Enum\Enum::equals()

There’s no difference in functionality, it breaks because of the final keyword.

Don’t get me wrong, I welcome the addition of the method to this package, it just shouldn’t be final unless you’re tagging a new major version.