Hi

On 4/4/24 02:54, Jordan LeDoux wrote:
If make a class final, users will not be able to add arbitrary methods, so
I think making each method final. Although it is possible to completely
separate behavior between method and opcode calculations, this is
inconsistent and confusing to users and should be avoided.



Right, if a class is not final but has only final methods (including
constructor) and no protected properties then it allows people to extend it
but not break any encapsulation or (I think) impose any more BC
requirements on the maintainer (unless we care about conflicting with
method names of child classes when updating). It lets people just do
something a bit like adding 'extension methods' in C#. I like it. People
could write e.g. `$bcChildNumber->isPrime()` instead of
`BcNumberUtils::isPrime($bcNumber)`


Yeah, I suspect the most common child class will be something like "Money"
that additionally has a parameter denoting what currency the value is in,
since that is by far the most common use case for arbitrary precision math
in PHP. Making the calculation methods final should do fine in my opinion.

Your `Money` example would allow for unsound and/or non-sense behavior, such as:

    $fiveEuros = new Money(5, 'EUR');
    $tenDollars = new Money(10, 'EUR');

    $what = $fiveEuros + $tenDollars;

What would you expect to be in $what? A `BcMath\Number(15)`?

----------------

The BcMath\Number class *should* absolutely be final, as a number is a number is a number. Allowing extension just to be able to write $number->isPrime() instead of isPrime($number) will allow for very confusing code, such as the example above, with no way to work around it in userland. It also makes interoperability between two different libraries that expect their own extensions to work very painful.

Consider the following example:

    class PrimalityTestingNumber extends Number {
        public function isPrime(): bool { }
    }

    class ParityTestingNumber extends Number {
        public function isEven(): bool { }
        public function isOdd(): bool { }
    }

If I now want to create a function to check whether a number is an even prime, I need to do something like this:

    function isEvenPrime(Number $n) {
return (new PrimalityTestingNumber($n))->isPrime() && (new ParityTestingNumber($n))->isEven();
    }

This use case would be much better solved in a generic way using something like this "Extension Methods" proposal: https://externals.io/message/118395#118395

Best regards
Tim Düsterhus

Reply via email to