> To the original question, there's two reasons that __toString() was
> deliberately omitted from enums:
>
> 1. To discourage their use as "fancy strings". Enums are their own type,
> independent of any other. Making them usable as 95% strings partially defeats
> their purpose.
I disagree with the idea that we need to take this extreme of a stance when it
comes to the notion of protecting the developer from themselves. There are a
lot of really value use cases where it makes sense to have a string-backed enum
. Not allowing developers to cast it to a string isn't doing anything but
making people type $enum->value instead of (string)$enum -- so if someone wants
to defeat their purpose this isn't stopping them. It is, however, making the
language inconsistent because I literally have a enumeration defined by strings
and there is literally no way to make PHP treat it like a string. This makes
APIs sloppy imo because consider something like this:
function foo(string|Stringable $bar) {}
Because of these limitations this blows up into a much uglier thing in order
accomplish what IMO should be a straightforward task:
function fooThatWantsString(string|Stringable|UnitEnum $bar)
{
if(($bar instanceof UnitEnum) && !is_string($bar->value)) {
throw InvalidArgumentException('This is exactly the sort of thing we are trying
to get rid of with type hinting');
} else {
$bar = $bar->value;
}
$bar = (string)$bar;
}
Of course, you could also pass $bar->value higher up the call stack but it's
much cleaner IMO to let the function call be smart enough to typecast as
necessary. What's the point of a Stringable interface if we can't actually
implement __toString() for it? Note again we can implement JsonSerializable and
nothing complains when enum serializes to a simple string.
> 2. We still intend to add associated values to enums at some point (aka ADTs,
> aka tagged unions), and... we're not really sure yet if that will impact
> __toString() at all. It may, it may not, we don't know. So for now we're
> keeping our options open by disallowing __toString(), in case it ends up
> being needed for some ADT-related behavior in the future.
__toString() should return a string, if an enum literally represents a string
constant it makes zero sense for it to ever return anything but that string
constant. I don't think this is something ADTs or tagged unions or anything of
the sort should play a role in deciding.
John