On Thu, May 23, 2024, at 1:35 AM, Robert Landers wrote:
> For what it's worth, the biggest downside to this decision is in
> upgrading old/legacy projects to use enums. Most of the time, you want
> to convert a const to an enum, and that also usually means it will be
> a backed enum. Since there's no way to cast a backed enum to a
> string/int, you have to instead add ->value (I really don't understand
> the difference; casting would have been much more elegant); this
> almost always results in lots of hidden runtime errors. At the last
> couple of places, after seeing the damage the conversion could do,
> doing this conversion was simply off-limits. Maybe by now, there is
> some reliable tooling to handle this automatically... I haven't
> looked. The point remains that it is a strange decision to use
> `->value` but not allow `(string)` or `(int)` or allow even
> implementing it yourself.
Union types are the correct solution here:
function move(string $direction, Player $player) { ... }
becomes
function move (Direction|string $direction, Player $player) {
if (is_string($direction)) {
$direction = Direction::from($direction);
}
// We now have a normalized enum to work with.
}
The only catch there is inheritance, where it works fine if you jut expand the
implementers/children first, then the interface/parent. Then you can remove
the string option at some point in the future, going the other way
(interface/parent, then implementer/child).
--Larry Garfield