On 29/03/2023 16:31, Davey Shafik wrote:
On Mar 29, 2023, at 06:56, Rowan Tommins <rowan.coll...@gmail.com> wrote:

On Wed, 29 Mar 2023 at 14:22, Rokas Šleinius <rave...@gmail.com> wrote:

Ok so I am trying to find the argumentation here:
This is by design.
The point of enums is to be limiting.
This is clearly an assumption. That statement is not in the docs or
RFC, nor such an oversimplification makes logical sense to me, but
maybe you have a source to back it up..?

 From a theory point of view, *any* type definition is about limiting
allowed values. The difference between "mixed" and "integer" is that
"mixed" allows both 'Hello' and 42, but "integer" does not - it defines a
tighter limit.

In the same way, saying "I accept an error code" means "I accept an error
code *and nothing else*" - the definition of what is and what isn't an
"error code" is deliberately a *limit* on the values that you accept.



Re: problem in the OP
You are approaching the design of this in a fundamentally wrong way.
The described problem is dealing with error *codes* not *types*


An enum is a type, so that's why George was talking about types. He was
making the same point, in different words, as I did: the relationship
between types implied by the keyword "extends" is not the relationship you
want in this case.



The set in question is *finite*, as you say of course, but much larger
and different in principle than in the solution you are proposing.
Problem in OP is looking for a way for end users to keep adding new
domains to the error codes passed to the parent system to be handled.

This is the key point - if you pass an error code that didn't previously
exist, the existing system *won't* be able to handle it.

That's why enums are inherently restrictive: the system wants to be able to
say "this is the list of error codes I understand, don't give me anything
else".

If you have a system that accepts the new codes as well as the old ones,
you can use a union type declaration as George says:

enum AdditionalErrorCode {
   case Code_456;
}

class ExtendedErrorHandler extends StandardErrorHandler {
   public function handle(StandardErrorCode|AdditionalErrorCode $code) {
        switch ( $code ) {
            case AdditionalErrorCode::Code_456:
               // handling for new code goes here
            break;
            default:
                // assert($code instanceof StandardErrorCode);
                parent::handle($code);
            break;
       }
   }
}
The issue of contention here is that inheritance isn't the correct mechanism for reusing 
enum definitions to expand on them. What about allowing "use" syntax  like 
traits?

enum HttpErrors {
    case HTTP_STATUS_400;
    case HTTP_STATUS_401;
     …
}

enum ApiErrors {
    use HttpErrors;

    case JsonParserError;
    case GraphQLParserError;
}

Now you have ApiErrors::HTTP_STATUS_400 etc without ApiErrors being is-a 
HttpErrors.

That would make a lot of sense, and I was just having similar thoughts myself.

ApiErrors isn't the same enum, or an extension of HttpErrors: it's a new Enum, but it does include all HttpErrors cases (and methods) without the need to duplicate code, and any new cases that are subsequently added to HttpErrors will automatically be incorporated in ApiErrors.


--
Mark Baker

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

Reply via email to