Re: String enums & __toString()
| From: | John Coggeshall | Date: | Sat, 17 Aug 2024 00:47:20 +0000 |
| Subject: | Re: String enums & __toString() | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-125014@lists.php.net to get a copy of this message | ||
> 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