Skip to content

Instantly share code, notes, and snippets.

@sshymko
Last active February 16, 2020 04:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sshymko/c3780dbe47880edf442339a7e931ea95 to your computer and use it in GitHub Desktop.
Save sshymko/c3780dbe47880edf442339a7e931ea95 to your computer and use it in GitHub Desktop.
PHP7 function/method signature overloading
<?php
declare(strict_types=1);
function overload(callable ...$implementations): callable
{
return function (...$args) use ($implementations) {
$error = new \LogicException('Invalid overloaded implementations');
foreach ($implementations as $candidate) {
try {
return $candidate(...$args);
} catch (\TypeError $e) {
$error = $e;
}
}
throw $error;
};
}
@sshymko
Copy link
Author

sshymko commented Feb 11, 2020

Usage example:

<?php
declare(strict_types=1);

class Calculator
{
    public function add(...$args)
    {
        return overload(
            function (int $num1, int $num2): int {
                return $num1 + $num2;
            },
            function (\GMP $num1, \GMP $num2): \GMP {
                return gmp_add($num1, $num2);
            }
        )(...$args);
    }
}


$calc = new Calculator();
$one = gmp_init(1);
$two = gmp_init(2);

print_r($calc->add(1, 2));        // 3
print_r($calc->add($one, $two));  // GMP Object([num] => 3)
print_r($calc->add(1.25, 2));     // TypeError: Argument 1 passed to Calculator::{closure}() must be an instance of GMP, float given

Note: declare longer signatures before ones with subset of arguments of matching types.

@sshymko
Copy link
Author

sshymko commented Feb 13, 2020

Released the overloading implementation as a Composer package:
https://github.com/upscalesoftware/stdlib-overloading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment