On Wed, 29 Mar 2023 at 13:30, G. P. B. <george.bany...@gmail.com> wrote:

> On Wed, 29 Mar 2023 at 09:31, Rokas Šleinius <rave...@gmail.com> wrote:
> > Enums were implemented as final so they cannot be extended nor can extend
> > anything else.
> >
>
> This is by design.
> Enumerations are in type theory parlance sum types.
> Objects in PHP, in general, are what are called product types.
>


I was just about to write a response along the same lines. I think the
confusion comes because in Java-style OOP, the keyword "extends" actually
does two things at once:

1. Takes the existing definition and adds to or over-rides parts of it
2. Takes the existing type and declares a sub-type

What you actually want to do with an enum is:

1. Take the existing definition and add cases to it
2. Take the existing type and declare a *super-type*

To give a concrete example of why, consider Christian's hypothetical:

> Imagine a Randomizer is much, much slower for certain boundaries and it
is decided that some programs do not care about Closed/Open but instead
care more about speed. So they would want to use something like
IntervalBoundary::Fastest.

If we use the normal definition of "extends", we could say this:

enum PerfIntervalBoundary extends IntervalBoundary {
   case Fastest;
}

Now we have an enum with three cases, which is what we wanted. But we've
also declared a *sub-type*: we've said that "every PerfIntervalBoundary
is-a IntervalBoundary". That means that anywhere that previously expected
an IntervalBoundary, we can pass PerfIntervalBoundary::Fastest - but none
of the existing Randomizer classes will know what to do with it!

What we actually wanted to do is leave all the existing uses of
IntervalBoundary alone, but create a new WeirdPerfRandomizer which accepts
the new type. We wanted to list "PerfIntervalBoundary" as the input type,
but still be able to pass it IntervalBoundary::Closed.

In short, we want to say "every IntervalBoundary is-a PerfIntervalBoundary"
- the relationship is the other way around.

As George says, this can be implemented right now by using a union type
constraint, like PerfIntervalBoundary|IntervalBoundary, which means "allow
any case of PerfIntervalBoundary as well as any value of IntervalBoundary".

If we wanted to support it more directly, we would need a new keyword to
make clear that this is *not* a sub-type relationship - perhaps something
like "expands", "allows", or "encompasses".

Regards,
-- 
Rowan Tommins
[IMSoP]

Reply via email to